反转字符串总结

1.反转字符串

在这里插入图片描述

反转字符串

这里是我们接触到的第一道反转字符串的例题
我们可以使用双指针来完成首位的反转
注意注意的是,这类题可能需要StringBulider这个容器

class Solution {
    public void reverseString(char[] s) {
        int left=0;
        int right =s.length-1;

        //快慢指针交换首位
        while(left<right){//利用了a^b^b=a这一特性
            s[left]^=s[right];
            s[right]^=s[left];
            s[left]^=s[right];
            left++;
            right--;
        }
    }
}

2.反转字符串 II

在这里插入图片描述
反转字符串 II

这道题只是增加了一些条件,实际上的思路还是不变的。
我们需要在for循环的条件上思考i变化的条件,以2k为一组,前k个我们反转,后k个保持不变即可。
严格把握住前k个的首位两项。

class Solution {
    public String reverseStr(String s, int k) {
        char[] ch = s.toCharArray();//将字符串转换为数组
        for(int i = 0; i < ch.length; i += 2 * k){
            int start = i;
            //这里是判断尾数够不够k个来取决end指针的位置
            int end = Math.min(ch.length - 1, start + k - 1);
            //用异或运算反转 
            while(start < end){
                ch[start] ^= ch[end];
                ch[end] ^= ch[start];
                ch[start] ^= ch[end];
                start++;
                end--;
            }
        }
        return new String(ch);
    }
}

3.替换空格

在这里插入图片描述
替换空格

本题与前两道题有所不同,我们需要额外的辅助空间。然后遍历字符串,将空格替换为“%20”,其余的不变。全部塞进辅助空间内。
另外,我们需要注意equals的类型强转。

class Solution {
    public String replaceSpace(String s) {
        StringBuilder sb =new StringBuilder();
        if(s==null) return null;

        for(int i=0;i<s.length();i++){
            //如果当前字符串时空格
            if(" ".equals(String.valueOf(s.charAt(i)))){//注意将char类型转换位String类型
               sb.append("%20");//将此位置添加为%20
            }else{
                sb.append(s.charAt(i));
            }
            
        }
        return sb.toString();//注意:输出String类型,要将StringBuilder转换为String
    }
}

4.翻转字符串里的单词

在这里插入图片描述
翻转字符串里的单词

本题考查的知识点非常多
我们可以大体分为3步:
1.去掉空格
2.反转字符串(整体反转)
3.反转单词(局部反转)

class Solution {
    /**
      1.去掉空格(在前面、后面或者单词间包含多余的空格)
      2.反转字符串
      3.反转单词
     */
    public String reverseWords(String s) {
        StringBuilder sb= removeSpace(s);
        reverseString(sb,0,sb.length()-1);
        reverseEachWoed(sb);
        return sb.toString();
    }


    //去掉空格
    private StringBuilder removeSpace(String s){
        StringBuilder sb =new StringBuilder();
        int left =0;
        int right = s.length()-1;
        while(s.charAt(left)==' ') left++;//从前面去空格
        while(s.charAt(right)==' ') right--;//从后面去空格
        //去掉中间的空格
        while(left<=right){
            char ch = s.charAt(left);
            if(ch!=' '||sb.charAt(sb.length()-1)!=' '){//核心代码
                sb.append(ch);
            }
            left++;
        }
        return sb;
    }


    //反转字符串
    private void reverseString(StringBuilder sb,int left,int right){
        while(left<right){
            char temp =sb.charAt(left);//临时存储
            sb.setCharAt(left,sb.charAt(right));//将字符串中指定的位置的字符替换成目标字符
            sb.setCharAt(right,temp);//将字符串中指定的位置的字符替换成目标字符
            left++;
            right--;
        }
    }

    //反转单词
    private void reverseEachWoed(StringBuilder sb){
        int start = 0;
        int end = 1;
        int n = sb.length();
        while (start < n) {
            while (end < n && sb.charAt(end) != ' ') {
                end++;
            }
            reverseString(sb, start, end - 1);
            start = end + 1;
            end = start + 1;
        }
    }
}

5.左旋转字符串

在这里插入图片描述
左旋转字符串

本题思路和上题大致相同
1.反转区间为前n的子串(局部)
2.反转区间为n到末尾的字串
3.反转整个字符串(整体)

class Solution {
    /**
        1.先局部反转(前n项) 
        2.再反转剩余的
        3.再全体反转   
     */
    public String reverseLeftWords(String s, int n) {
        StringBuilder sb =new StringBuilder(s);
        int right=s.length()-1;
        
        reverseString(sb,0,n-1);
        reverseString(sb,n,right);
        return sb.reverse().toString();


    }


    /**
       反转字符串
     */
    private void reverseString(StringBuilder sb,int left,int right){
        while(left<right){
            char temp = sb.charAt(left);//暂时存储当前第一个位置的字符
            sb.setCharAt(left,sb.charAt(right));
            sb.setCharAt(right,temp);
            left++;
            right--;
        }
       
    }
}
<think>好的,我现在需要回答用户关于如何在C++中实现字符串反转的问题。首先,我得整理一下已有的信息。用户提供了四个引用,都是关于C++反转字符串的不同方法,包括使用循环逐个字符添加到新字符串、原地反转、局部反转结合整体反转来实现右旋,以及使用标准库函数。 首先,我需要确定用户的需求是什么。用户可能想知道不同的反转方法,以及它们的优缺点。根据引用中的代码示例,可以总结出几种不同的方法: 1. **创建新字符串反转方法**:引用[1]中的方法,通过遍历原字符串,将每个字符添加到新字符串的前面,从而生成反转后的字符串。这种方法简单易懂,但需要额外的空间,空间复杂度是O(n)。 2. **原地反转**:引用[3]和[4]中的方法,直接在原字符串上进行字符交换。比如,引用[4]的代码通过循环交换字符直到中间位置,这样不需要额外的空间,空间复杂度为O(1)。另外,使用标准库的reverse函数也是一种简便的方式,如引用[4]中注释掉的代码。 3. **局部反转实现右旋**:引用[2]中的例子展示了如何通过三次局部反转来达到右旋字符串的效果。这种方法虽然主要用于右旋,但展示了反转操作在更复杂场景中的应用,比如空间复杂度为O(1)的操作。 接下来,我需要将这些方法分门别类,并解释每种方法的实现步骤和优缺点。需要注意用户可能对时间复杂度和空间复杂度有疑问,所以需要明确说明。 另外,用户提供的引用中有一些具体的代码示例,比如引用[1]的代码使用了一个新字符串,而引用[2]和[4]则直接在原字符串上操作。需要指出这些方法的不同之处,比如是否需要额外空间,是否修改原字符串等。 在组织回答时,应该先介绍最简单的方法,比如使用标准库的reverse函数,因为这是最快捷的方式。然后介绍手动实现的方法,比如原地交换,再提到其他变种如右旋的实现。这样用户可以根据需求选择不同的方法。 同时,要注意代码示例的正确性。例如,引用[1]中的代码使用了string类型,而引用[4]处理的是vector<char>,可能需要说明这两种数据结构的区别,但用户的问题是关于字符串反转,所以可能主要关注string类型。 需要检查是否有错误的地方,比如引用[2]中的右旋方法是否有效。根据引用[2]中的代码,通过三次反转确实可以实现右旋,例如,先将整个字符串反转,然后反转前n个字符,再反转后面的字符,这样的确可以达到右移n位的效果。这点需要正确解释。 最后,生成相关问题的时候,需要覆盖时间复杂度、优化方法、应用场景等,例如比较不同方法的效率,或者如何处理特殊字符等。 总结步骤: 1. 分点介绍不同方法,包括使用新字符串、原地交换、标准库函数、局部反转组合应用。 2. 每种方法给出代码示例,并说明优缺点。 3. 确保代码正确,符合C++语法。 4. 引用对应的参考文献,正确标注引用标记。 5. 生成相关问题,帮助用户深入理解。</think>在C++中实现字符串反转的常用方法如下,具体选择取决于是否需要原地修改或利用额外空间: ### 一、创建新字符串反转方法(需要O(n)空间) 通过遍历原字符串,将每个字符插入新字符串头部: ```cpp #include <bits/stdc++.h> using namespace std; int main() { string s1 = "hello", s2; for(int i=0; i<s1.size(); i++) s2 = s1[i] + s2; // 字符前插实现反转 cout << s2; // 输出"olleh" } ``` 优点:代码简洁,不修改原字符串 缺点:需要额外空间[^1] ### 二、原地交换法(空间O(1)) 通过首尾双指针交换字符: ```cpp void reverseString(string &s) { int left=0, right=s.size()-1; while(left < right) swap(s[left++], s[right--]); } ``` 或手动实现交换: ```cpp for(int i=0; i<len/2; i++){ int j = len - i - 1; char tmp = s[i]; s[i] = s[j]; s[j] = tmp; } ``` 优点:内存效率高 缺点:直接修改原字符串[^4] ### 三、使用STL算法库 直接调用`reverse`函数: ```cpp #include <algorithm> reverse(s.begin(), s.end()); ``` 优点:一行代码实现 缺点:隐藏实现细节,学习时建议手动实现 ### 四、进阶应用:三次反转实现右旋 通过局部反转组合完成字符串旋转: ```cpp void reverse(string &s, int l, int r) { while(l < r) swap(s[l++], s[r--]); } int main() { string s = "abcdefg"; int k = 2; // 右旋位数 reverse(s, 0, s.size()-1); // 全反转 reverse(s, 0, k-1); // 前k位反转 reverse(s, k, s.size()-1); // 剩余部分反转 cout << s; // 输入"cdefgab" } ``` 原理:整体反转 → 前k位反转 → 后部反转 = 右旋k位[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值