哈喽!今天我们来聊聊一个非常有趣的话题——反转字符串!我们在日常生活中经常会遇到需要将字符串颠倒过来的情况,比如翻转一句话或者颠倒一个名字的顺序。这个时候,就可以用到反转字符串算法了。
首先,让我们来思考一下这个算法的实现。最简单直接的方式是使用一个循环,从字符串的末尾开始,将每个字符逐个放到一个新的字符串中。不过,这个方法看起来有点笨重,我们有更聪明的办法。
让我们来尝试一个巧妙的思路。我们可以定义两个指针,一个指向字符串的开头,一个指向字符串的末尾。然后,我们将这两个指针指向的字符进行交换,直到两个指针相遇为止。通过这种方式,我们可以逐步实现字符串的反转。
具体来说,我们可以从字符串的两端开始,依次交换它们指向的字符。每次交换完之后,两个指针向中间靠拢一步,直到它们相遇。这样,整个字符串就被完美地颠倒过来了。
好了,现在让我们来看一下具体的实现代码。假设我们的字符串是一个可变字符数组,首先我们需要定义两个指针,一个指向字符串开头的位置,一个指向字符串结尾的位置。然后,我们可以使用一个循环来依次交换两个指针指向的字符,直到两个指针相遇为止。
下面是实现代码:
class Solution {
public:
void reverseString(vector<char>& s) {
int left = 0;
int right = s.size() - 1;
while (left < right)
{
swap(s[left],s[right]);
left++;
right--;
}
}
};
我们接着来聊聊一道相关的题目——541. 反转字符串 II。这道题是对刚才我们提到的反转字符串算法的一个扩展。
题目要求我们对给定的字符串进行一种特殊的反转操作,具体来说,是将字符串中的每间隔 2k 个字符的前 k 个字符进行反转。换句话说,我们需要把每个长度为 k 的子串进行反转,而保留其它部分的字符顺序不变。
这个题目的解题思路其实与我们之前提到的反转字符串算法类似,但稍加变化。需要改变循环时的一些变量。但整体循环变量自己理解就行,不同人写法可能不同。
class Solution {
public:
string reverseStr(string s, int k) {
int start = 0;
int end = start + k;
while(start < s.size())
{
if(end > s.size())
{
reverse(s.begin() + start,s.end());
}
else
{
reverse(s.begin() + start,s.begin() + end);
}
start = start + 2 * k;
end = end + 2 * k;
}
return s;
}
};
接下来让我们继续进行替换空格的练习吧!
通常来讲,我们确实是可以用replace来进行基础的操作,但是面试中,还是最好以双指针法经验面试官。
这道题目要求我们替换字符串中的空格,要求以时间复杂度O(N)和空间复杂度O(1)的方式进行。我们可以使用双指针法来解决这个问题。
具体的步骤如下:
- 遍历字符串,统计空格的个数,计算出替换后的字符串的总长度;
- 创建一个新的字符数组,长度为原字符串的总长度,并将原字符串的字符依次复制到新数组中;
- 使用两个指针,一个指向原字符串的末尾,另一个指向新数组的末尾;
- 从后向前遍历新数组,当遇到空格时,将"%20"依次插入指针指向的位置,并分别向前移动指针;
- 最后,将新数组转换为字符串并返回。
下面是实现代码:
class Solution {
public:
string replaceSpace(string s) {
int count = 0;
int oldsize = s.size();
for(int i = 0; i < s.size(); i++)
{
if (s[i] == ' ')
{
count++;
}
}
s.resize(s.size() + count * 2);
int newsize = s.size();
int j = oldsize;
int i = newsize;
while ( j < i && j >= 0)
{
if(s[j] != ' ')
{
s[i] = s[j];
i = i - 1;
j = j - 1;
}
else
{
s[i] = '0';
s[i-1] = '2';
s[i-2] = '%';
i = i - 3;
j = j - 1;
}
}
std::cout << "my new string" << s << endl;
return s;
}
};
下面我们来看151.反转字符串中的单词
这道题目要求我们反转字符串中的单词顺序,要求不使用额外的空间,只在原字符串上进行操作。我们可以使用双指针法来解决这个问题。
具体的步骤如下:
- 先将字符串整体反转;
- 使用两个指针,一个指向当前单词的起始位置,一个指向当前单词的结束位置;
- 遍历字符串,当遇到空格时,将当前单词进行反转,并更新下一个单词的起始位置;
- 最后一个单词没有空格,所以需要单独进行反转。
下面是实现代码
class Solution {
public:
string removeExtraSpace(string s)
{
int fastIndex = 0;
int slowIndex = 0;
for(;fastIndex < s.size(); fastIndex++)
{
if(s[fastIndex] != ' ')
{
break;
}
}
for(;fastIndex < s.size(); fastIndex++)
{
if(fastIndex > 0 && s[fastIndex] == ' ' && s[fastIndex-1] == ' ')
{
;
}
else
{
s[slowIndex] = s[fastIndex];
slowIndex++;
}
}
if (slowIndex > 1 && s[slowIndex-1] == ' ')
{
s.resize(slowIndex-1);
}
else
{
s.resize(slowIndex);
}
return s;
}
string reverseWords(string& s) {
string new_s = removeExtraSpace(s);
reverse(new_s.begin(), new_s.end());
int start = 0;
for (int i = 0; i < new_s.size(); i++) {
if (new_s[i] == ' ') {
reverse(new_s.begin() + start, new_s.begin() + i);
start = i + 1;
}
}
reverse(new_s.begin() + start, new_s.end());
return new_s;
}
};
下面我们来看,剑指Offer58-II.左旋转字符串题目。
这道题目要求我们将一个字符串的前n个字符移到字符串的末尾,实现字符串的左旋转操作。我们可以通过字符串切片和字符串拼接的方式来解决这个问题。
具体的步骤如下:
- 使用字符串切片,将字符串分为前n个字符和剩余的字符两部分;
- 将剩余的字符与前n个字符拼接,即可得到左旋转后的字符串。
但如果要求我们在原字符串上进行操作,不能申请额外空间。
针对这个要求,我们可以利用字符串的翻转操作来实现左旋转字符串。
具体的步骤如下:
- 先将整个字符串的前n反转;
- 再将后n个字符进行反转;
- 最后将整个进行反转。
class Solution {
public:
string reverseLeftWords(string s, int n) {
reverse(s.begin(),s.begin() + n);
reverse(s.begin() + n , s.end());
reverse(s.begin(),s.end());
return s;
}
};
&spm=1001.2101.3001.5002&articleId=132321379&d=1&t=3&u=8beab5ae47454aeb9030706a1c5a8869)
2891

被折叠的 条评论
为什么被折叠?



