LeetCode151.反转字符串中的单词
题目:151. 反转字符串中的单词 - 力扣(LeetCode)
思路:
1.先把字符串中多余的空格去除
2.反转整个字符串
3.再单独反转字符串中的每个单词
代码:
class Solution {
public:
void removeExtraSpaces(string& s){
int slow = 0;
for(int fast = 0; fast < s.size(); fast++){
if(s[fast] != ' '){
if(slow != 0) s[slow++] = ' ';
while(fast < s.size() && s[fast] != ' '){
s[slow++] = s[fast++];
}
}
}
s.resize(slow);
}
void reverse(string& s, int start, int end){
for(int i = start, j = end; i < j; i++, j--){
swap(s[i], s[j]);
}
}
string reverseWords(string s) {
removeExtraSpaces(s);
reverse(s, 0, s.size() - 1);
int start = 0;
for(int i = 0; i <= s.size(); i++){
if(s[i] == ' ' || i == s.size()){//当到达空格或者字符串尾,说明一个单词遍历结束或者整个字符串遍历结束
reverse(s, start, i-1);//翻转[start,i-1],即翻转一个单词
start = i + 1;/*更新start,此时i指向空格,让start指向空格的下一个位置即
i+1*/
}
}
return s;
}
};
剑指 Offer 58 - II. 左旋转字符串
题目:剑指 Offer 58 - II. 左旋转字符串 - 力扣(LeetCode)
思路:
1.先反转前n个字符
2.再反转n到字符串末尾个字符
3.最后反转整个字符串
代码:
class Solution {
public:
void reverse(string& s,int start, int end){
for(int i = start, j = end; i < j; i++, j--){
swap(s[i], s[j]);
}
}
string reverseLeftWords(string s, int n) {
reverse(s, 0, n - 1);
reverse(s, n, s.size() - 1);
reverse(s, 0, s.size() - 1);
return s;
}
};
LeetCode28. 找出字符串中第一个匹配项的下标
题目:28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)
思路:这是一道典型的KMP算法,模式串和文本串的快速匹配,核心在于匹配过程中如何利用其已经匹配相同的部分,就是当匹配不成功时,模式串不用在从头开始匹配,而是j跳到其最大公共前缀的后一个位置,此时文本串中i指向其最大公共后缀的后一个位置,因为文本串和模式串相同部分的最大公共前缀和后缀肯定也相同。这儿涉及到一个next[]数组,模式串中j的回跳就是根据next[]数组实现,j是根据其前一个元素j-1在next数组中的值来往回跳,即j = next[j - 1]。
具体分析见:代码随想录 (programmercarl.com)
代码:
class Solution {
public:
void getnext(int* next, const string& s){
//j指向前缀末尾的位置,i指向后缀末尾的位置
int j = 0;
next[0] = 0;
for(int i = 1; i < s.size(); i++){//i从下标1的位置开始
while(j > 0 && s[j] != s[i]){//如果前后缀末尾不相同的情况,就要向前回退,j回退到前一个元素再next数组中的值
j = next[j - 1];//j
}
if(s[j] == s[i]){//如果 s[i] 与 s[j] 相同,那么就同时向后移动i 和j 说明找到了相同的前后缀,同时还要将j(前缀的长度)赋给next[i], 因为next[i]要记录相同前后缀的长度。
j++;
}
next[i] = j;
}
}
int strStr(string haystack, string needle) {
int next[needle.size()];
getnext(next, needle);
int j = 0;
for(int i = 0; i < haystack.size(); i++){
while(j > 0 && needle[j] != haystack[i]){
j = next[j - 1];
}
if(needle[j] == haystack[i]){
j++;
}
if(j == needle.size()){
return(i - needle.size() + 1);
}
}
return -1;
}
};
LeetCode459. 重复的子字符串
题目:459. 重复的子字符串 - 力扣(LeetCode)
思路:还是用KMP算法,在由重复子串组成的字符串中,最长相等前后缀不包含的子串就是最小重复子串,其中next数组记录的就是最长相等前后缀,len是字符串的长度,如果len % (len - (next[len - 1] + 1)) == 0 ,则说明数组的长度正好可以被 (数组长度-最长相等前后缀的长度) 整除 ,说明该字符串有重复的子字符串。
具体分析见:代码随想录 (programmercarl.com)
代码:
class Solution {
public:
void getnext(int* next, const string& s){
int j = 0;
next[j] = 0;
for(int i = 1; i < s.size(); i++){
while(j > 0 && s[j] != s[i]){
j = next[j - 1];
}
if(s[j] == s[i]){
j++;
}
next[i] = j;
}
}
bool repeatedSubstringPattern(string s) {
int next[s.size()];
getnext(next, s);
int j = 0;
int len = s.size();
if(next[len - 1] != 0 && len % (len - next[len - 1]) == 0){
return true;
}
return false;
}
};