代码随想录算法训练营第7天|344.反转字符串、541. 反转字符串II、替换数字、151.翻转字符串里的单词

LeetCode344

2025-01-28 17:39:48 星期二

题目描述:力扣344
文档讲解:代码随想录(programmercarl)344.反转字符串
视频讲解:《代码随想录》算法视频公开课:字符串基础操作! | LeetCode:344.反转字符串

代码随想录视频内容简记

本题仍然是使用双指针法进行解决,在头部设置一个指针,在尾部设置一个指针,然后两两交换,和206.反转链表的方式有不一样,不是两个指针都在头部,同时向尾部移动。和977.有序数组的平方,还有15.三数之和18.四数之和的移动方式是一致的。

另外注意一点,就是关于交换两个元素的值。除了定义一个tmp变量进行交换,还可以使用异或运算。注意两数不同(0和1)异或得1,两数相同异或得0(0和0,或者1和1)

s[i] = s[i] ^ s[j];
s[j] = s[j] ^ s[i];
s[i] = s[i] ^ s[j];

这样的方式也可以完成两数的交换

梳理

  1. 注意要分类讨论一种情况,就是字符串的长度为奇数或者为偶数

  2. 如果为奇数,则最中间的一位仍然不用移动

  3. 如果为偶数,则正好可以两两交换

大致代码内容

  1. 只需设置一个循环for (int i = 0, j = nums.size() - 1; i < nums.size() / 2; i++, j--)
  2. swap (nums[i], nums[j])

LeetCode测试

完整代码如下

点击查看代码
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]);
        }
    }
};

LeetCode541

题目描述:力扣541
文档讲解:代码随想录(programmercarl)541. 反转字符串II
视频讲解:《代码随想录》算法视频公开课:字符串操作进阶! | LeetCode:541. 反转字符串II

代码随想录视频简记

梳理

  1. 一个for循环,操作语句可以每次控制2k个距离,遍历至最后,剩余的字符串长度不够2k为止

  2. 每次对2k个字符串中前k个字符串进行反转

  3. 最后剩余的字符串如果足够k个长度,则反转前k个

  4. 剩余的字符串如果不够k个长度,则全部反转

大致代码内容

  1. for (int i = 0; i < s.size(); i += 2k)

  2. if (i + k <= s.size()) reverse(s, i, i + k),注意,无论是否遍历至剩余字符串,i + k如果足够,那就必须要进行反转。至于这里为什么要加上=,是因为如果s = "abc"k = 3,无法遍历至2k个,则按照题目要求,这三个字符串要全部进行反转。

这一步实现的就是“最后剩余的字符串如果足够k个长度,则反转前k个”,反转完成后剩余的字符串不够2k个,会直接成为剩余字符串,不够k个,则按照下面的全部进行反转

  1. i + k不进行反转的情况只有一种,那就是剩余字符串的长度不够k个,if (i + k > s.size())所以要全部进行反转

LeetCode测试

这个题的代码虽然简短,但是感觉理解起来并不简单

点击查看代码
class Solution {
public:
    string reverseStr(string s, int k) {
        for (int i = 0; i < s.size(); i += 2 * k) {
            if (i + k <= s.size()) reverse(s.begin() + i, s.begin() + i + k);
            if (i + k > s.size()) reverse(s.begin() + i, s.end());
        }
        return s;
    }
};

替换数字

题目描述:卡玛网替换数字
文档讲解:代码随想录(programmercarl)541. 反转字符串II

这属于一道扩充字符串的题目,关键仍然在双指针

梳理

  1. 首先查询字符串中的数字个数

  2. 对字符串的长度进行扩充,注意这个代码是s.resize(s.size() + count * 5),这里要乘5不要忘记

  3. 定义一个left指针指向替换之前的字符串,一个right指针指向替换之后的字符串。而遍历的终止条件就是left指针把原先的字符串遍历完

  4. 循环遍历字符串,注意循环的终止条件是left >= 0,这里为什么不是left > 0呢?其实这里可以举个极端的例子,例如字符串为"1",但是仍然要进行一次循环,将"1"变为"number",但是left = 1 - 1之后初始为0,写成left > 0就直接结束了,所以不能这么写

卡玛网测试

代码不太好写,里面好多小细节感觉

点击查看代码
# include<iostream>
using namespace std;
int main() {
    string s, result;
    cin >> s;
    int count = 0, oldSize;
    oldSize = s.size();
    for (int i = 0; i < s.size(); i++) {
        if (s[i] <= '9' && s[i] >= '0') count++;
    }
    s.resize(s.size() + count * 5);
    int left, right;
    for (left = oldSize - 1, right = s.size() - 1; left >= 0;) {
        if (s[left] <= '9' && s[left] >= '0') {
            s[right--] = 'r';
            s[right--] = 'e';
            s[right--] = 'b';
            s[right--] = 'm';
            s[right--] = 'u';
            s[right--] = 'n';
            left--;
        }
        // 如果不是数字
        else {
            s[right--] = s[left--];}
       
    }
    cout << s << endl;
}   

151.翻转字符串里的单词

题目描述:力扣151
文档讲解:代码随想录(programmercarl)151.翻转字符串里的单词
视频讲解:《代码随想录》算法视频公开课:字符串复杂操作拿捏了! | LeetCode:151.翻转字符串里的单词

代码随想录视频内容简记

核心内容是去除空格,仍旧使用的是双指针法

梳理

  1. 首先去除字符串里所有的空格

  2. 对字符串大小进行更新

  3. 将所有的字符进行反转

  4. 对每个单词进行反转

大致代码内容

  1. 去除空格。首先想到的是如果fast指针指向的内容不为空,则赋值给slow指针。同时,因为第一个单词之前是没有空格的,其余的单词之间都是有空格的。所以如果slow指针指向的不是第一个单词,if (slow != 0) s[slow++] = ' '。为了让每个单词之间有' '进行连接,slow发生变化之后,一定是一次性指向一个完整的单词并发生移动,那么,就必然要使用while来让fast指针为slow指针进行完整的赋值。

注意这里的条件判断,必须得带上fast < s.size(),因为假如fast走到最后一个单词,后面没有空格了,这个while就没有出口了


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++];
		}
	}
}

这个注意,刚开始的时候循环条件写的i,后面循环体用的fast,没看出来,结果一直报错,不要写错了。

  1. s.resize(slow);

  2. reverse(s.begin(), s.end())对所有的字符进行反转,这个注意,如果是直接用的库函数reverse()的话,有两个参数,一个是s的起始,一个是s的终止。

  3. 对单词进行翻转,for (int i = 0; i <= s.size(); i++),注意k哥说过,reverse()库函数进行反转是一个左闭右开区间的,所以我们对最后一个单词进行反转的时候,他的if判断条件必须等于s.size(),所以我们在循环的时候就不能只写i < s.size()

LeetCode测试

感觉不好写这个题

点击查看代码
class Solution {
public:
    string reverseWords(string s) {
        int fast = 0, 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);

        reverse(s.begin(), s.end());
        int start = 0;
        for (int i = 0; i <= s.size(); i++) {
            if (s[i] == ' ' || i == s.size()) {
                reverse(s.begin() + start, s.begin() + i);
                start = i + 1;
            } 
        }
        return s;
    }
};
posted on   bnbncch  阅读(1823)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示