字符串 part01:344.反转字符串,541. 反转字符串II,剑指Offer 05.替换空格,151.翻转字符串里的单词*,剑指Offer58-II.左旋转字符串

344.反转字符串

题目

在这里插入图片描述

库函数reverse的底层实现

思考历程

和反转链表有什么区别?

区别于反转链表:字符串可以看作是字符的数组,反转数组可以直接交换值,链表是逐一修改指向。

解题方法(双指针向中间靠拢)

  • 流程:
    1、字符串vector也是数组
    2、用双指针从左端、右端开始,互相交换
    3、然后向中间移动
  • 图解
    在这里插入图片描述

难点

  • 犯错:字符串最后一个字符不应该是 j = s.size(),而是 j = s.size()-1
  • 新知识点:for循环多个参数

代码

class Solution {
public:
    void reverseString(vector<char>& s) {
        for(int i = 0, j = s.size()-1;i<j;i++,j--){
            swap(s[i],s[j]);
        }
    }
};

541. 反转字符串II(难)

题目

在这里插入图片描述

思考历程

看不懂题目的规则

题意:每2k个字符,反转它的前k个字符;如果不够k个,就全部反转。

解题方法(简化为只有两种情况)

  • 流程:
    1、i 每次以2k的长度去遍历
    2、只要i及其后面还有k个字符,就可以反转前k个字符
    3、剩余情况,就把剩余字符全部反转
  • 图解
    花式反转字符串

难点

  1. 巧妙:把需要反转前k个字符的两种情况合并了、i每次+2k
  2. 找不准边界条件:从i数起前k个字符:[i, i+k-1],i+k==s.size()是符合“剩余字符有k个”的边界
  3. continue的用法:提前结束本轮遍历,进入下一轮遍历

代码

class Solution {
public:
    string reverseStr(string s, int k) {
        for(int i=0; i<s.size();i=i+2*k){
            if(i+k<=s.size()){//取等号的时候,刚好还剩[i,i+k-1]这k个字符
                reverse(s.begin()+i,s.begin()+i+k);//reverse是左闭右开
                continue;
            }
            else{
                reverse(s.begin()+i,s.end());
            }
        }
        return s; 
    }
};

剑指Offer 05.替换空格

题目

在这里插入图片描述

解题方法(双指针,新数组根据旧数组赋值)

  • 流程:
    1、先统计空格数目,然后扩充成新的数组
    2、从旧数组右端和新数组右端开始遍历,旧数组元素是空格就替换,旧数组元素不是空格就原样复制
  • 图解
    在这里插入图片描述

难点

  1. 难点:为什么从后向前进行操作,
  • 好处1:不用申请新数组。
  • 好处2:避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。
  1. 难点:为什么i从旧数组的末尾开始

因为新数组是从后往前填充的,所以需要从旧数组末尾开始移动,去判断新数组该填什么值。(旧数组是新数组的依据)

代码

class Solution {
public:
    string replaceSpace(string s) {
        int count = 0;
        int oldSize = s.size();
        for(int i = 0; i<oldSize; i++){//统计空格的数量
            if(s[i] == ' '){
                count++;
            }
        }
        int newSize = oldSize + count*2;//%20比空格多两个字符
        s.resize(newSize);//新数组
        for(int i = oldSize-1,j = newSize-1;i<j;i--,j--){
            if(s[i]==' '){
                s[j] = '0';
                s[j-1] = '2';
                s[j-2] = '%';
                j = j-2;
            }
            else{
                s[j] = s[i];
            }
        }
        return s;
    }
};

151.翻转字符串里的单词(难)

题目

待填坑

思考历程

解题方法

难点

代码

在这里插入代码片

剑指Offer58-II.左旋转字符串

题目

在这里插入图片描述

思考历程

想不到

解题方法(反转再反转再反转)

先反转前k位,再反转剩余部分,最后反转整个字符串

  • 图解
    在这里插入图片描述

难点

  1. 难点:想不到这种解法
  2. 对string不熟悉
    1、可以通过[]方式取字符,与数组用法一致
    2、与数组的区别:可以理解为是一个字符数组
    3、string、char*、vector的区别
  • string:C++ 标准库中的string类,提供了高级的字符串处理方式,是一个对象。
  • char*:C风格的字符串,是一个指向字符的指针,指向字符串的起始位置。
  • vector:C++ 标准库中的vector类,用于表示一组字符,是一个对象,不如string专业
  1. reverse算法的使用:reverse(开始迭代器,结束迭代器)

代码

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        reverse(s.begin(),s.begin()+n);
        reverse(s.begin()+n,s.end());
        reverse(s.begin(),s.end());
        return s;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值