代码随想录第八天| Leecode 344. 反转字符串、Leecode 541 反转字符串 II

Leecode 344 反转字符串

题目描述

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

  • 示例 1:
    • 输入:s = ["h","e","l","l","o"]
    • 输出:["o","l","l","e","h"]
  • 示例 2:
    • 输入:s = ["H","a","n","n","a","h"]
    • 输出:["h","a","n","n","a","H"]

解题思路与代码展示

如果只是需要交换两个变量位置的话,常用的方法都是使用一个temp变量,用于临时存放被覆盖的值,再将其覆盖另一个值。而本题需要交换整个字符串,那么相应地就是需要交换字符串长度除以2次,每次交换的元素两边逐渐往中心移动。即最先交换首尾两个元素,第二个和倒数第二个···一直到最后交换中心的元素。此时需要注意,如果字符串长度为奇数,最后中心剩下一个元素并不需要交换;如果最后中心剩下两个元素,则直接把这两个元素也交换后停止即可。

那么即使同时考虑奇数长度和偶数长度的情形,需要交换的次数也只是字符串长度/2,因为如果是奇数在除以2并放入int型变量后,多出来的0.5直接被省略。由此可以得到代码如下:

class Solution {
public:
    void reverseString(vector<char>& s) {
       int n = s.size()/2;  // 左右交换的次数,如果长度为偶数则两两交换,奇数则最中间一个不交换,其余交换
       for(int i = 0; i < n; i++){
            char temp = s[i];   // 使用temp来实现交换操作
            s[i] = s[s.size()-i-1]; // 左侧第i个元素,和其对称到右侧的元素进行交换
            s[s.size()-i-1] = temp;
       } 
    }
};

上面代码只额外使用了一个char型变量就完成了整个字符串的反转,同时时间复杂度为\(O(n)\)

Leecode 541 反转字符串 II

题目描述

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

  • 示例 1:
    • 输入:s = "abcdefg", k = 2
    • 输出:"bacdfeg"
  • 示例 2:
    • 输入:s = "abcd", k = 2
    • 输出:"bacd"

解题思路与代码展示:

本题是上面反转字符串的花样变体,我的思路是套用原本的反转函数,并加上一些判断,如果满足条件则调用反转。这个过程中需要注意各种情况的条件判断。因为题目中提到每2k就要执行对前k个反转,那么可以考虑使用递归或是循环的方式来解决都行,在我下面的代码中使用了递归的方式。

class Solution {
public:
    string reverseStrPart(string s, int left, int right){ // 对字符串中left到right和之间的部分进行反转
        while(left < right){
            char temp = s[left];
            s[left++] = s[right];
            s[right--] = temp;
        }
        return s;
    }

    string reverseStr(string s, int k, int start = 0) { // 本轮周期从start开始计数
        if( start >= s.size()-1) return s;  // 如果start在字符串最后,则说明整个字符串都已经反转,直接return
        int end = start + k-1; // 要反转的部分从start到end及其之间,这个区间中包含了k个数
        if(end > s.size()-1) end = s.size()-1; // 但如果start之后的字符串长度已经不够k个,那么令end等于最后一位
        return reverseStr(reverseStrPart(s,start,end), k, end+k+1); // 反转start到end之间,同时递归调用,更新字符串,以及更新新的反转区间
    }
};

上面代码的时间复杂度为\(O(n)\),只需要遍历一遍字符串即可完成反转。

今日总结

今天题比较少,感觉还挺轻松,自己又刷了两道动态规划的题但暂时不写上来了,等之后刷到动态规划再来写,今天还是早点休息吧。

今天学会了在github上提交pr,然后把前几天画的反转链表的那个动图提交上去了。当时画完只是提了一个issue,今天才懂issue和pr的区别。。

posted on 2025-04-02 22:10  JQ_Luke  阅读(1132)  评论(0)    收藏  举报