跟着代码随想录刷题第十七天(2023.5.3) -- 字符串1~2

一、Leetcode第344题:反转字符串

思路:可以发现,无论是字符数组的大小是奇数还是偶数,首尾元素调换的次数都是 s.size() / 2,那么直接一个for循环就可以搞定!元素交换时可以用swap!

class Solution {
public:
    void reverseString(vector<char>& s) {
        int n = s.size();  // 字符数组长度
        for(int ii = 0; ii < (n/2); ii++) {  // 无论奇数还是偶数  交换次数都是一样的,都是 n/2 舍弃小数
            swap(s[ii], s[n-1-ii]);
            // char tmp = s[ii];
            // s[ii] = s[n - 1 - ii];  // 注意下标边界为   n - 1
            // s[n - 1 -ii] = tmp;
        }
    }
};

也可以直接调用reverse函数:

// 直接调用reverse函数
class Solution {
public:
    void reverseString(vector<char>& s) {
        reverse(s.begin(), s.end());
    }

};

也可以像随想录一样使用双指针

// 使用双指针
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]);
        }
    }
};

二、Leetcode第541题:反转字符串||

思路:一开始想着先把正常情况即 剩余字符大于2k个 时进行单独处理,再处理两种特殊情况,于是代码写的又臭又长!代码如下:

class Solution {
public:
    string reverseStr(string s, int k) {
        int n = s.size();  // 定义n为数组总长度,在后面循环中会用到
        int left = 0;  // 左指针
        int right = left + k - 1;  // 右指针
        int nums = 0;  // 用于记录  “计数” 了多少次
        // 正常计数,即剩余字符大于2k个
        while(n >= 2*k) {
        // 交换字符  注意终止条件为 ii < jj或(left+right+1)/2!后面的也是如此,可以多试几次!
            for(int ii = left, jj = right; ii < (left + right + 1)/2; ii++, jj--) {
                swap(s[ii], s[jj]);
            }
            n -= 2*k;  // 更新剩余字符数量
            nums++;
            left = nums*2*k;  // 更新左指针
            right = left + k - 1;  // 更新右指针
        }

        // 之前调试时的两种特殊情况,即剩余字符=1  和 k大于剩余字符数量, 后来发现不需要
        // if(s.size()-left == 1) return s;

        // if(k >= s.size()-left) {
        //     for(int ii = left, jj = s.size()-1; ii < (left + s.size())/2; ii++, jj--) {
        //         swap(s[ii], s[jj]);
        //     }
        //     return s;            
        // }

        // 如果剩余字符少于 k 个,则将剩余字符全部反转。
        if(s.size()-left < k) {
            for(int ii = left, jj = s.size() - 1; ii < (s.size() + left)/2; ii++, jj--) {
                swap(s[ii], s[jj]);
            }
            return s;
        }
        // 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
        else if(s.size()-left >= k && s.size()-left < 2*k) {
            for(int ii = left, jj = right; ii < (left + right + 1)/2; ii++, jj--) {
                swap(s[ii], s[jj]);
            }
        }
        return s;
    }
};

这代码写的真差劲!把for循环中的反转封装了一下(也可以直接用reverse),好看一丢丢了:
 

class Solution {
public:
    // 自定义反转reverse
    void myreverse(string& s, int left, int right) {
        for(int ii = left, jj = right; ii < jj;  ii++, jj--) {
            swap(s[ii], s[jj]);
        }
    }
    string reverseStr(string s, int k) {
        int n = s.size();  // 定义n为数组总长度,在后面循环中会用到
        int left = 0;  // 左指针
        int right = left + k - 1;  // 右指针
        int nums = 0;  // 用于记录  “计数” 了多少次
        // 正常计数,即剩余字符大于2k个
        while(n >= 2*k) {
            // 交换字符  注意终止条件为 (left+right+1)/2 或者直接 ii < jj!后面的也是如此,可以多试几次!
            myreverse(s, left, right);
            n -= 2*k;  // 更新剩余字符数量
            nums++;
            left = nums*2*k;  // 更新左指针
            right = left + k - 1;  // 更新右指针
        }

        // 如果剩余字符少于 k 个,则将剩余字符全部反转。
        if(s.size()-left < k) {
            myreverse(s, left, s.size() - 1);

        }
        // 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
        else if(s.size()-left >= k && s.size()-left < 2*k) {
            myreverse(s, left, right);
        }
        return s;
    }
};

看了随想录的解法,发现只要剩余字符大于等于k个,都是将剩余字符的前k个字符进行反转!这样就可以把程序放入一个 for循环中,单独处理剩余字符小于k个的情况就可以了!代码如下:

class Solution {
public:
    string reverseStr(string s, int k) {
        for (int i = 0; i < s.size(); i += (2 * k)) {
            // 1. 每隔 2k 个字符的前 k 个字符进行反转
            // 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
            if (i + k <= s.size()) {
                reverse(s.begin() + i, s.begin() + i + k );
            } else {
                // 3. 剩余字符少于 k 个,则将剩余字符全部反转。
                reverse(s.begin() + i, s.end());
            }
        }
        return s;
    }
};

代码是真的简洁呀!以后思考问题一定得多想想,找最简单的解法!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值