LeetCode | 字符串反转,旋转相关题目整合 |

力扣189.旋转数组(直接点击即可跳转题目)

在这里插入图片描述

思路分析

  • 举个栗子,如果要k=15,size也是7,那么k%size=1,实际就是旋转了两个周期,然后右旋转一次,所以就是 7 1 2 3 4 5 6 ,那么我们直接reverse三次问题就解决了

代码实现

class Solution {
    
    
public:
    void rotate(vector<int>& nums, int k) 
    {
    
    
        k=k%nums.size();
        
        reverse(nums.begin(),nums.end());
        reverse(nums.begin(),nums.begin()+k);
        reverse(nums.begin()+k,nums.end()); 
    }
};

力扣344.反转字符串

在这里插入图片描述

思路分析

  • 双指针过

代码实现

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

力扣541.反转字符串Ⅱ

在这里插入图片描述

思路分析

  • 刚开始思路想着就暴力解法,后来看了题解,就用了题解的方法
  • 我们可以将2k作为一段字符进行操作,就会存在以下两种情况
  • 首先是[ k ]≤字符长度<[ 2k ],这种情况就反转前k个字符
  • 第二种情况是字符少于k个这种情况就直接反转全部

代码实现

class Solution {
    
    
public:
    string reverseStr(string s, int k) 
    {
    
    
        
        for(int i=0;i<s.size();i+=2*k)
        {
    
    
            if(i+k<s.size())
            {
    
    
                //反转前k个
                reverse(s.begin()+i,s.begin()+i+k);
            }
            else
            {
    
    
                //反转全部
                reverse(s.begin()+i,s.begin()+s.size());
            }
        }
        return s;
    }
};

力扣151.翻转字符串里的单词(字节题库)

在这里插入图片描述

思路分析

  • 看完题目初步思路是:

  • 1.先把整个字符串反转 2.再翻转局部的字符串 3.再去处理多余空格

  • 但是实现了半天也没有结果,还是看了题解,大概明白了两种比较好理解的方法

  • 第一种就是O(n)解法

  • 第二种是O(1)解法,函数全部自己实现

代码实现

O(n)

  • 我们从后往前地添加单词(包括标点符号)进 res
  • 每添加完一个单词,我们就给 res 手动加上一个空格
  • 最后返回 res 即可

(戳这里)

class Solution {
    
    
public:
    string reverseWords(string s) {
    
    
        int len = s.length();

        if (len == 0) {
    
    
            return "";
        }

        int j = len - 1;
        string res = "";

        while (j >= 0) {
    
    
            if (s[j] == ' ') {
    
    
                // 当 s[j] 是空格时,j 不断左移
                j--;
                continue;
            }

            while (j >= 0 && s[j] != ' ') {
    
    
                // 注意 while 里必须用 && 短路求值,且 j >= 0 要放前面
                // 不然如果 j 变成 -1,那么计算 s[j] 会发生溢出错误!
                j--;
            }
            
            int pos = j; // 用 pos 保存 j 当前的位置
            j++; // j 现在指向的是一个空格,需要右移一位才能指向一个单词的开头

            while (s[j] != ' ' && j < len) {
    
    
                // 向 res 中添加单词
                res += s[j];
                j++;
            }

            j = pos; // j 回到新添加的单词的最左端再往左一个空格处
            res += ' '; // 单词添加完毕后需要加上一个空格
        }

        if (res[res.length() - 1] == ' ') {
    
    
            // 删除 res 最后一位的多余空格
            res.erase(res.length() - 1, 1);
        }

        return res;
    }
};



O(1)
这里代码贴的是一道题解的(戳这里)

class Solution {
    
    
public:
    // 反转字符串s中左闭又闭的区间[start, end]
    void reverse(string& s, int start, int end) 
    {
    
    
        for (int i = start, j = end; i < j; i++, j--) 
        {
    
    
            swap(s[i], s[j]);
        }
    }

    // 移除冗余空格:使用双指针(快慢指针法)O(n)的算法
    void removeExtraSpaces(string& s) 
    {
    
    
        int slowIndex = 0, fastIndex = 0; // 定义快指针,慢指针
        // 去掉字符串前面的空格
        while (s.size() > 0 && fastIndex < s.size() && s[fastIndex] == ' ') 
        {
    
    
            fastIndex++;
        }
        for (; fastIndex < s.size(); fastIndex++) 
        {
    
    
            // 去掉字符串中间部分的冗余空格
            if (fastIndex - 1 > 0
                && s[fastIndex - 1] == s[fastIndex]
                && s[fastIndex] == ' ') 
            {
    
    
                continue;
            } 
            else 
            {
    
    
                s[slowIndex++] = s[fastIndex];
            }
        }
        if (slowIndex - 1 > 0 && s[slowIndex - 1] == ' ') {
    
     // 去掉字符串末尾的空格
            s.resize(slowIndex - 1);
        } else {
    
    
            s.resize(slowIndex); // 重新设置字符串大小
        }
    }

    string reverseWords(string s) 
    {
    
    
        removeExtraSpaces(s); // 去掉冗余空格
        reverse(s, 0, s.size() - 1); // 将字符串全部反转
        int start = 0; // 反转的单词在字符串里起始位置
        int end = 0; // 反转的单词在字符串里终止位置
        bool entry = false; // 标记枚举字符串的过程中是否已经进入了单词区间
        for (int i = 0; i < s.size(); i++) 
        {
    
       // 开始反转单词
            if ((!entry) || (s[i] != ' ' && s[i - 1] == ' ')) 
            {
    
    
                start = i; // 确定单词起始位置
                entry = true; // 进入单词区间
            }
            // 单词后面有空格的情况,空格就是分词符
            if (entry && s[i] == ' ' && s[i - 1] != ' ') 
            {
    
    
                end = i - 1; // 确定单词终止位置
                entry = false; // 结束单词区间
                reverse(s, start, end);
            }
            // 最后一个结尾单词之后没有空格的情况
            if (entry && (i == (s.size() - 1)) && s[i] != ' ' ) 
            {
    
    
                end = i;// 确定单词终止位置
                entry = false; // 结束单词区间
                reverse(s, start, end);
            }
        }
        return s;
    }
};


剑指offer58-Ⅱ.左旋转字符串(字节题库)

在这里插入图片描述

思路分析

  • 我们先把 abcdefg 字符串分为两部分
  • part1:ab part2:cdefg
  • 分别reverse part1part2
  • 得到 part3:bagfedc
  • reverse part3得到cdefgab

代码实现

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

猜你喜欢

转载自blog.csdn.net/qq_45657288/article/details/113768991