代码随想录【Day 8】 | 344.反转字符串、541. 反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串
344. 反转字符串
题目链接:344.反转字符串
卡尔文字讲解
解题思路重点:
对于字符串,我们定义两个指针(也可以说是索引下标),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。
代码实现:
class Solution {
public:
void reverseString(vector<char>& s) {
int left = 0;
int right = s.size() - 1;
while ( left < right ){
swap( s[left++], s[right--] );
}
}
};
541. 反转字符串II
题目链接:541.反转字符串II
卡尔文解
解题思路及注意事项:
这道题目其实也是模拟,实现题目中规定的反转规则就可以了。
一些同学可能为了处理逻辑:每隔2k个字符的前k的字符,写了一堆逻辑代码或者再搞一个计数器,来统计2k,再统计前k个字符。
其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。
因为要找的也就是每2 * k 区间的起点,这样写,程序会高效很多。
代码实现:
class Solution {
private:
void reverseString( string &s, int start, int end ) {
while ( start < end ){
swap( s[ start++ ], s[ end-- ] );
}
}
public:
string reverseStr(string s, int k) {
for ( int i = 0 ; i < s.size(); i += ( 2*k )){
if (( i + k ) <= s.size() ){
reverseString(s, i, ( i + k - 1));
}
else{
reverseString(s, i, s.size() - 1);
}
}
return s;
}
};
剑指Offer 05.替换空格
题目链接:05.替换空格
卡尔文解
解题思路及注意事项:
如果想把这道题目做到极致,就不要只用额外的辅助空间了!
- 首先扩充数组到每个空格替换成 “%20” 之后的大小。
- 然后从后向前替换空格,也就是双指针法,过程如下:
- latest_end 指向新长度的末尾,old_end 指向旧长度的末尾。
代码实现:
class Solution {
public:
string replaceSpace(string s) {
int space_count = 0;
int orig_size = s.size();
for ( int i = 0; i < s.size(); i++ ){
if ( s[i] == ' ') space_count++;
}
// Increase original string size.
s.resize(s.size() + (space_count * 2));
int latest_size = s.size();
// '%20'
for( int old_end = (orig_size - 1), latest_end = (latest_size - 1);
latest_end > old_end; old_end--, latest_end-- ){
if ( s[ old_end ] != ' ' ){
s[ latest_end ] = s[ old_end ];
}
else{
s[ latest_end ] = '0';
s[ latest_end - 1 ] = '2';
s[ latest_end - 2 ] = '%';
//latest_end - 2 instead of - 3 , because there is another -- by the end of for loop.
latest_end -= 2;
}
}
return s;
}
};
151.翻转字符串里的单词
题目链接:151.反转字符串里的单词
卡尔文解
解题思路及注意事项:
将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒序了,那么再把单词反转一下,单词不就正过来了。
所以解题思路如下:
- 移除多余空格
- 将整个字符串反转
- 将每个单词反转
举个例子,源字符串为:"the sky is blue "
移除多余空格 : “the sky is blue”
字符串反转:“eulb si yks eht”
单词反转:“blue is sky the”
这样我们就完成了翻转字符串里的单词。
代码实现:
class Solution {
private:
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 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 ) ;
}
public:
string reverseWords(string s) {
removeExtraSpaces( s ); // Remove all reduntant spaces.
reverse( s, 0, s.size() - 1 ); // Reverse whole string.
// Start reverseing each word in string to recover original order of each word.
for ( int start = 0, idx = 0; idx <= s.size(); idx++ ){
if ( idx == s.size() || s[ idx ] == ' ' ){
reverse(s, start, idx - 1 );
start = idx + 1;
}
}
return s;
}
};
剑指Offer58-II.左旋转字符串
题目链接:剑指Offer58-II.左旋转字符串
卡尔文解
解题思路及注意事项:
将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒序了,那么再把单词反转一下,单词不就正过来了。
所以解题思路如下:
- 反转区间为前n的子串
- 反转区间为n到末尾的子串
- 反转整个字符串
- 最后就可以达到左旋n的目的,而不用定义新的字符串,完全在本串上操作。
代码实现:
class Solution {
private:
void reverseStr( string &s, int start, int end ){
for ( int i = start, j = end; i < j; i++, j-- ){
swap( s[i], s[j] );
}
}
public:
string reverseLeftWords(string s, int n) {
int size = s.size();
// Reverse 0 -> ( n-1 )
reverseStr(s, 0, n - 1 );
// Reverse n -> ( size - 1 )
reverseStr( s, n, size - 1 );
// Reverse whole string
reverseStr(s, 0, size - 1 );
return s;
}
};