代码随想录day8|Leetcode: 344.反转字符串 541. 反转字符串II 剑指Offer 05.替换空格 151.翻转字符串里的单词 剑指Offer58-II.左旋转字符串

题目链接:344. 反转字符串

c++代码(双指针)------------->(编写reserve函数)

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

思路

前后双指针不断靠近中间,交换两边的数据,就可以完成交换,这道题和“有序数组的平方差不多”,都是两边指针,

  • 如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。毕竟面试官一定不是考察你对库函数的熟悉程度, 如果使用python和java 的同学更需要注意这一点,因为python、java提供的库函数十分丰富。如果库函数仅仅是 解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。


题目链接:541. 反转字符串 II

c++代码

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

思路

每次移动2*k步,移动前提前判断,如果可以过k步,就翻转k个,如果不够,翻转后面的全部

所以当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章

为什么可以用库函数呢,因为不是关键解题步骤。



题目链接:剑指 Offer 05. 替换空格

c++代码(双指针)

class Solution {
public:
    string replaceSpace(string s) {
        int count = 0;  
        int ordlen = s.size();
        for (int i = 0; i < ordlen; i++) {
            if (s[i]== ' ') count++;//计算空格数量
        }

        s.resize(ordlen + 2 * count);//申请空间
        int newlen = s.size();
        int i = newlen;
        for (int j = ordlen; j >= 0; j--) {
            if (s[j] != ' ') {//不为空格,就直接覆盖
                s[i] = s[j];
                i--;
            } else {为空格就填充%20
              s[i] = '0';
              s[i - 1] = '2';
              s[i - 2] = '%';
              i -= 3; 
            }
        }
        return s;
    }
};

思路

计算空格个数,根据需要加东西申请空间,一个指针在原来位置后面,一个指针在在现在位置最后面,第一个指针不断往前推,如果不是空格就加入新字符串最后,如果是,就加入%20再进行遍历,相当于往前推三个位置

问题:为什么要从后向前填充,从前向后填充不行么?

从前向后填充每次填充都会向后移动后面的元素,就会变成O(n*2)的时间复杂度了



题目链接:151. 反转字符串中的单词

官方讲解---代码随想录

c++代码

class Solution {
public:
//移除空格 并 在每个单词中加入 空格
    void removeExtraSpaces(string& s) {
        int slow = 0;
        for (int fast = 0; fast < s.size(); ++fast) {//外层循环进行判断空格,直到找到单词位置
             if (s[fast] != ' ') {//找到单词位置
                 if(slow != 0 ) s[slow++] = ' ';//如果第一次找到单词位置 就不用加空格,否则前面就有单词,说明要加入空格
                 while(s[fast] != ' ' && fast < s.size()) {//补上该单词,遇到空格说明单词结束。
                     s[slow++] = s[fast++];
                    //  fast++;
                    //  slow++;
                 }
             }
           }
           s.resize(slow);
        }  
//翻转全局位置再翻转局部位置
    string reverseWords(string s) {
       removeExtraSpaces(s);
       int len = s.size();
       reverse(s.begin(), s.begin() + len);//翻转全局位置
       int res = 0; 
       for (int i = 0; i <=len; i++) {
           if (i == len || s[i] == ' ') {  //下一个是空格或则到末尾都可以
               reverse(s.begin() + res, s.begin() + i);//左闭右开
               res = i + 1;
           }
       }

       return s;
    }
};

思路

 只要理解怎么移除空格就可以差不多写出这道题目,,这部分和27.移除元素 (opens new window)的逻辑是一样一样的,本题是移除空格,而 27.移除元素 就是移除元素。

步骤:

  1. 删除字符串空格,并在每个单词后添加空格
  2. 翻转全局单词
  3. 翻转各个局部单词

所以这里我还是提高一下本题的难度:不要使用辅助空间,空间复杂度要求为O(1)。

怎么完成第一步,删除并添加空格

可以看下图:

代码随想录day8|Leetcode: 344.反转字符串 541. 反转字符串II 剑指Offer 05.替换空格 151.翻转字符串里的单词 剑指Offer58-II.左旋转字符串_第1张图片

 反转最后一个单词

就不能判断后面是否为空格了,需要判断是否到达了最后



题目链接:剑指 Offer 58 - II. 左旋转字符串

c++代码

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        reverse(s.begin(), s.end());//e.end()返回最后一个元素下一个元素的下标
         reverse(s.begin(), s.begin() + s.size() - n);
         reverse(s.begin() + s.size() - n , s.end());

        return s;
    }
};

步骤:

  1. 全局反转
  2. 局部反转第一个单词
  3. 局部反转第二个单词

 为了让本题更有意义,提升一下本题难度:不能申请额外空间,只能在本串上操作。那么我们可以想一下上一题目字符串:花式反转还不够! (opens new window)中讲过,使用整体反转+局部反转就可以实现反转单词顺序的目的。依然可以通过局部反转+整体反转 达到左旋转的目的。

代码随想录day8|Leetcode: 344.反转字符串 541. 反转字符串II 剑指Offer 05.替换空格 151.翻转字符串里的单词 剑指Offer58-II.左旋转字符串_第2张图片



总结

在这篇文章344.反转字符串 (opens new window),第一次讲到反转一个字符串应该怎么做,使用了双指针法。

然后发现541. 反转字符串II (opens new window),这里开始给反转加上了一些条件,当需要固定规律一段一段去处理字符串的时候,要想想在for循环的表达式上做做文章。

后来在151.翻转字符串里的单词 (opens new window)中,要对一句话里的单词顺序进行反转,发现先整体反转再局部反转 是一个很妙的思路。

最后再讲到本题,本题则是先局部反转再 整体反转,与151.翻转字符串里的单词 (opens new window)类似,但是也是一种新的思路。

你可能感兴趣的:(代码随想录一刷,leetcode,算法,数据结构,c++)