代码随想录day10-字符串(2) & 双指针总结
1、LeetCode 151 反转字符串中的所有单词
题目分析:
本题要求反转字字符串中的所有单词,并且要求我们去除多余的空格,比如连续的空格,前导空格,以及尾随空格等等。我们的第一步应该就是去除多余的空格。然后我们可以观察到,如果我们对字符串整体进行反转,那么得到肯定也可以反转每个单词,但是,单词内部的顺序也被反转了,所以还需要针对每个单词进行局部的反转,就可以得到答案。
步骤如下:
- 去除多余的空格;
- 整体反转;
- 局部反转。
题目解答:
class Solution {
public:
string reverseWords(string s) {
// 这个题比较技巧性,先整体反转,然后再局部反转,最后可以得到最终的答案
removeExtraSpace(s);
reverse(s, 0, s.size() - 1); // 整体反转
int left = 0;
for (int i = 0; i < s.size(); i++) { // 局部反转
if (s[i] == ' ') {
reverse(s, left, i -1);
left = i + 1;
}
}
reverse(s, left, s.size() - 1); // 反转最后一个单词
return s;
}
void removeExtraSpace(string& s) {
int index = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] != ' ') s[index++] = s[i]; // 如果不是空格,就正常添加就行
else {
if (i > 0 && s[i - 1] != ' ') {
s[index++] = s[i]; // 这种可以去除重复的以及前导空格,但是有可能最后一个会是空格(如果存在尾随空格
}
}
}
if (s[index - 1] == ' ') index--; // 单独去除
s.resize(index);
}
void reverse(string& s, int start, int end) {
for (int i = start, j = end; i < j; i++, j--) {
swap(s[i], s[j]);
}
}
};
2、剑指Offer 58 左旋转字符串
题目分析:
本题的思路很简单,左旋转就是将字符串的前k个字符,放到最后面去就行了。最简单的思路就是使用一个新字符串存放前k个字符,然后遍历字符串,从k开始的后面的字符串的索引减k即可。
题目解答:
class Solution {
public:
string reverseLeftWords(string s, int n) {
int len = s.length();
if (len == 0) return "";
if (n > len) return s;
string str(s.begin(), s.begin() + n);
for (int i = n; i < len; i++) s[i - n] = s[i];
for (int i = len - n; i < len; i++) s[i] = str[i - len + n];
return s;
}
};
进阶:如果本题要求不开辟额外的空间,仅仅原地左旋转呢?
这样一来,本题就比较技巧性了,但是大致思路跟上面一个题是一样的,也是局部反转加整体反转。我们观察到,如果我们先反转前k个字符,再反转后面len-k个字符,最后整体反转即可。解答如下:
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;
}
};
3、LeetCode 28 找出字符串中第一个匹配项的下标
题目分析:
本题如果运用暴力法的话,其实也是非常简单的,我们遍历haystack字符串,然后然后依次判断长为needle的字串是否等于neddle,如果是,返回当前索引。如果遍历完整个字符串都没有的话,返回-1即可。
题目解答:
class Solution {
public:
int strStr(string haystack, string needle) {
// 暴力法求解
int len1 = haystack.size();
int len2 = needle.size();
if (len2 > len1) return -1;
if (haystack == needle) return 0; // 这里的条件只能是判断字符串是否相等,不能判断长度是否相等
for (int i = 0; i < len1; i++) {
if (haystack[i] == needle[0] && i + len2 - 1 < len1 && haystack.substr(i, len2) == needle)
return i;
// 第一个条件是为了快速判断符不符合条件,可以快速筛查,如果第一个字符都不相等,没有比下去的必要了
// 第二个为了防止越界
}
return -1;
}
};
如果本题不使用暴力法,很多答案使用的都是KMP算法,这里目前还没了解,学习之后来进行补充。(3.5)
4、LeetCode 459 重复的子字符串
本题同样的也是使用KMP算法,后续进行补充。(3.5)
本章只是浅浅的了解了一下字符串部分的内容,之前的双指针法在字符串这一类型的题目里面见的很多,此外,滑动窗口的方法在字符串中也是经常使用的,以后遇到了再进行总结。
意志是独一无二的个体所拥有的、以纠正自己的自动性的力量。——劳伦斯