思路:利用双指针进行字符串反转,i,j指数组头和尾,i,j下标指向元素两两交换,不断内缩,i也控制交换趟数。
代码:
void reverseString(vector& s) {
int j = s.size()-1;
int temp;
for(int i = 0;i < s.size()/2;i++,j--){
temp = s[i];
s[i] = s[j];
s[j] = temp;
}
}
思路:每次处理的数组可以看作区间大小为2k的子数组,则每次for前进以2k大小前进,题目虽然给了3个反转条件,可以整理下1.若有2k个字符,反转前k个 2.若剩下字符小于2k且大于等于k,则反转前k个 3.若剩下字符小于k个,反转剩下的;对于以上条件,没必要还去分别判断字符满足多少个,其核心就是当前子区间是否满足k个?满足就反转k个,不满足就反转剩下的。
代码:
string reverseStr(string s, int k) {
for(int i = 0;i < s.size();i += (2*k)){
if(i + k < s.size()){//
reverse(s.begin()+i,s.begin()+k+i);
continue;
}
reverse(s.begin()+i,s.begin()+s.size());//剩的字符小于k个
}
return s;
}
还需要注意.begin()是从哪算起的。是从当前下标索引的前面算起。如图:例s.begin()+0,s.begin()+2
要求其空间复杂度为O(1)
思路:1.删除多余空格 2.整个字符串反转 3.每个单词反转
1.删除多余空格指每个单词之间仅能保留一个空格,并且字符串的最前面和最后是没有空格的。删除空格可以看作是删除元素,该思路可以参考27.移除元素的双指针法,利用快指针寻找符合条件元素,慢指针用于存储元素。
2和3.一个单词反转两次就是其本身
void RemoveExtraSpaces(string &s){//删除多余空格,参考27.移除元素双指针法
int slow = 0;//快指针找符合条件的元素,慢指针为元素存放的位置
for(int fast = 0;fast < s.size();fast++){
if(s[fast] != ' '){//快指针遇到非空格就跳过(删除)
if(slow != 0) s[slow++] = ' ';//给单词之间添加空格,
//只有经过下面的while(已经存在一个单词),且再次进入上面的if(本次又至少存在一个单词),该if才会执行(给上个单词和这个单词添加空格)
while(fast < s.size() && s[fast] != ' '){//移动单词,如果遇到空格,则说明该单词结束
s[slow++] = s[fast++];
}
}
}
s.resize(slow);//重新定义s的大小,因为数组不能真正删除元素,只有覆盖,所以需要手动设置更新后的大小
}
void reverse(string &s,int start,int end){//左闭右开
end = end-1;
for(;start < end;start++,end--){
swap(s[start],s[end]);
}
}
string reverseWords(string s) {
RemoveExtraSpaces(s);//第一步.删除空格
reverse(s,0,s.size());//第二步,整体反转
for(int start = 0;start < s.size();){//第三步,子数组(单词)反转
int end = start;
while(end < s.size() && s[end] != ' ') end++;
reverse(s,start,end);
start = end+1;//更新下一个单词的起始位置
}
return s;
}
删除空格的另外一个解法利用erase函数删除,由于数组元素是不能删除的,只能覆盖,所以该函数时间复杂度O(n),又因为该函数外套了层for循环(需要一个一个找空格),所以整体的时间复杂度会是O()。如果用双指针法,时间复杂度仅O(n)
这两题在卡码网,且网站解析和思路更详细。