反转字符串
思路:在练习本题之前,复习了数组和链表的相关知识,这是因为字符串的本质可以视为数组,而比较反转链表与反转字符串的区别也很有价值,反转链表也是通过双指针来实现,只不过操纵的是指针,反转字符串虽然也是使用双指针,但是双指针指向的值才是交换的内容,区别还是比较大的。
KEY:本题最重要的就是要有双指针的思路,它可以使空间复杂度降到O(1),时间复杂度降到O(N)。
总结:双指针不论是在链表,数组,还是字符串中,都是常用的。
代码:
class Solution {
public:
void reverseString(vector<char>& s) {
for(int i=0,j=s.size()-1;i<s.size()/2;i++,j--){
swap(s[i],s[j]);
}
}
};
补充:注意边检条件的处理。学会使用简单例子。
反转字符串II
思路:本题做了些花样,题目要求不但要让反转实现,而且要在指定的区间反转,本题的重点是找到反转区间的规律,在循环反转的表达式上做文章。既然题目要求以2k为单位移动,我也可以让i一次+2k呀。
KEY:
首先还是表达式的修改。
其次要分析好三种情况:
第一种情况,够2k,直接反转前k个;
第二种情况,不够2k,但是够k个,仍然反转前k个,操作同第一种情况;
第三种情况,不够2k,也不够k,直接将末尾全部反转。
总结:遇到字符串中找规律的题目,往往可以在表达式上做做文章以取到好的效果。
代码:
class Solution {
public:
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()+i+k);//
continue;
}
reverse(s.begin()+i,s.end());
}
return s;
}
};
剑指offer05、替换空格
思路:这道题目的思路很妙,首先替换空格,那么应当会把字符串扩容,所以可以先统计出需要扩容的空间大小,接着要怎么替换呢?
这里又要用到双指针,一个指向新数组的末尾,一个指向旧数组的末尾,然后从后向前替换,之所以这么做,是因为从后向前可以避免从前向后需要做的数组后移的问题。
分析:旧指针不是指向空格,就意味着是新数组的元素,直接搬过来,如果旧指针指向的是空格,意味着在新数组应当填充的是替换的内容,倒序插入替换后的内容即可,插入完之后及时把新数组的指针前移别忘了。
总结:其实凡是这种数组填充类的操作,往往都可以通过先将数组扩容,再从后往前插入所需内容来解决,这样的空间复杂度是O(N),时间复杂度也是O(N),开销并不大,代码逻辑还是很清晰的。
代码:
class Solution {
public:
string replaceSpace(string s) {
int count=0;
int sOldsize=s.size();
for(int i=0;i<s.size();i++){
if(s[i]==' '){
count++;//记录需要扩充的单位次数
}
}
s.resize(sOldsize+2*count);
int sNewsize=s.size();
for(int i=sOldsize-1,j=sNewsize-1;i<j;i--,j--){
if(s[i]!=' '){
s[j]=s[i];
}else{
s[j]='0';
s[j-1]='2';
s[j-2]='%';
j-=2;
}
}
return s;
}
};
剑指offer58、左旋转字符串
思路:这道题关键是要理清思路,之前做反转字符串II的时候,是先把整体旋转(当然要先做去除空格的操作),再把局部旋转。这道题目也是花式旋转,也可以采用类似的方式来做,先局部旋转再整体旋转就可以解决这个问题。
步骤:
首先旋转前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;
}
};
题外话:系统默认的操作区间一般是左闭右开的,我们自己可以设置成左闭右闭或左闭右开。