代码随想录【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.替换空格

卡尔文解

解题思路及注意事项:

如果想把这道题目做到极致,就不要只用额外的辅助空间了!

  1. 首先扩充数组到每个空格替换成 “%20” 之后的大小。
  2. 然后从后向前替换空格,也就是双指针法,过程如下:
  3. 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.反转字符串里的单词

卡尔文解

解题思路及注意事项:

将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒序了,那么再把单词反转一下,单词不就正过来了。

所以解题思路如下:

  1. 移除多余空格
  2. 将整个字符串反转
  3. 将每个单词反转
    举个例子,源字符串为:"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.左旋转字符串

卡尔文解

解题思路及注意事项:

将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒序了,那么再把单词反转一下,单词不就正过来了。

所以解题思路如下:

  1. 反转区间为前n的子串
  2. 反转区间为n到末尾的子串
  3. 反转整个字符串
  4. 最后就可以达到左旋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;

    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值