151. 反转字符串中的单词
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]);
}
}
void removeExtraSpaces(string& s){
int slow = 0;
for (int i=0; i<s.size(); i++){
if(s[i]!=' '){
if (slow!=0) {s[slow++]=' ';}
while (i<s.size() && s[i]!=' '){
s[slow++]=s[i++];
}
}
}
s.resize(slow);
}
string reverseWords(string s) {
removeExtraSpaces(s);
reverse(s,0,s.size()-1);
int start=0; int a=0,b=0;
for (int i=0; i<=s.size();i++){
if(s[i]==' '|| i==s.size()){ // take care! 这边是s.size(),不是,因为在反转的时候左闭右闭的,同时还要兼顾在s[i]检索到' '的情况,所以需要搜索到s.siz()这一位(超越过数组最大位一位),这样才能在右闭的时候合上。
b=i;
reverse(s,a,b-1);
a=b+1;
}
}
return s;
}
关于这边通过双指针去除空格的方法还是非常巧妙的,我在这边把其中的链路再书写一下:
①.快指针查找到单词的首位
②.慢指针先跟着输入一个空格(在不是首位的时候),用于间隔
③.当快指针扫到不为空格的时候,慢指针跟随快指针同步字母。
在最后反转的主程序中,需要注意的是,是左闭右闭的情况,所以要取到s.size()这一位。
剑指 Offer 58 - II. 左旋转字符串、
class Solution {
public:
void getNext(vector<int> &next,const string& s){
int j=0;
next[0]=0;
for(int i=1; i<s.size(); i++){
while(j>0 && s[i]!=s[j]){
j=next[j-1];
}
if(s[i]==s[j]){j++;}
next[i]=j;
}
}
int strStr(string haystack, string needle) {
if(needle.size()==0){
return 0;
}
vector<int> next(needle.size()); //在vector定义中输入needle.size()就是定义了next数组的长度.
int j=0;
getNext(next,needle);
for (int i=0; i<haystack.size();i++){
while (j>0 && haystack[i]!=needle[j]){
j=next[j-1];
}
if( haystack[i]==needle[j]){
j++;}
if(j==needle.size()){
return(i-needle.size()+1);
}
}
return -1;
}
};
在第一个getNext形参中,别忘了next前面加了&,确保把数组中的数据传递至主函数。这和C语言中的语法是不同的,这边附上之前C语言中
其实创建next的过程就与后面寻找重复数组串是近乎一样的,关键就在于前缀的搜索结果对于后面的next数组的定义是有继承性的。
在查找数组的next数值是都会同next[j]进行比较,如果相同就进行直接的J++的继承。
每次i一碰壁(前后缀共同长度为0)就要从头开始,在每次碰壁后,next数组都要从零开始从新赋予值。