对于字符串,我们定义两个指针(也可以说是索引下标),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。
class Solution {
public:
void reverseString(vector<char>& s) {
int left = 0;
int right = s.size() - 1;
while ( left < right ){
swap( s[left++], s[right--] );
}
}
};
这道题目其实也是模拟,实现题目中规定的反转规则就可以了。
一些同学可能为了处理逻辑:每隔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;
}
};
如果想把这道题目做到极致,就不要只用额外的辅助空间了!
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;
}
};
将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒序了,那么再把单词反转一下,单词不就正过来了。
所以解题思路如下:
移除多余空格 : “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;
}
};
将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒序了,那么再把单词反转一下,单词不就正过来了。
所以解题思路如下:
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;
}
};