代码随想录算法训练营day08 | 344.反转字符串,541. 反转字符串II,剑指Offer 05.替换空格,151.翻转字符串里的单词,剑指Offer58-II.左旋转字符串


344.反转字符串

教程视频:https://www.bilibili.com/video/BV1fV4y17748
在这里插入图片描述

解法一:双指针

    public void reverseString(char[] s) {
        //左右指针
        int i=0,j=s.length-1;
        char temp;
        while(i<j){
            temp = s[i];
            s[i] = s[j];
            s[j] = temp;
            
            //s[l] ^= s[r];  //(^是 按位异或 操作)构造 a ^ b 的结果,并放在 a 中
            //s[r] ^= s[l];  //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b
            //s[l] ^= s[r];  //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换
            i++;
            j--;
        }
    }

541. 反转字符串II

教程视频:https://www.bilibili.com/video/BV1dT411j7NN/?vd_source=ddffd51aa532d23e6feac69924e20891
截图

解法一:转成字符数组进行交换

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

解法二:使用StringBuffer的 reverse() 方法

  • 当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。
  • 和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
  • 在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。
  • StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

在这里插入图片描述

在这里插入图片描述
使用StringBuffer要注意把不变的字符填充进去。

    public String reverseStr(String s, int k) {
        StringBuffer result = new StringBuffer();
        int length = s.length();
        int i = 0;
        while(i<length){
            // 与length进行比较,如果大于length了,那就将其置为length
            int firstK = (i+k<=length)?i+k:length;//firstK 是i~i+k字符内的下标
            int secondK = (i+2*k<=length)?i+2*k:length;//secondK 是i+k~i+2k字符内的下标

            //反转firstK中字符
            StringBuffer temp = new StringBuffer(s.substring(i,firstK));
            result.append(temp.reverse());

            // 如果firstK到secondK之间有元素,这些元素直接放入res里
            if(firstK<secondK){
                temp = new StringBuffer(s.substring(firstK,secondK));
                result.append(temp);
            }

            i+=2*k;
        }
        return result.toString();
    }

剑指Offer 05.替换空格

教程:https://programmercarl.com/%E5%89%91%E6%8C%87Offer05.%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC
在这里插入图片描述

解法一:复制时替换空格

    public String replaceSpace(String s) {
        StringBuffer res = new StringBuffer();
        for(int i = 0;i<s.length();i++){
            if(s.charAt(i)==' '){
                res.append("%20");
            }else{
                res.append(s.charAt(i));
            }
        }
        return res.toString();
    }

解法二:双指针(适合c++)

首先扩充数组到每个空格替换成"%20"之后的大小。然后从后向前替换空格。
优点:

  1. 不用申请新数组。降低了空间复杂度。
  2. 从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。降低了时间复杂度。

但java中的String类用指针处理过程繁琐,不适合用此解法


151.翻转字符串里的单词

教程视频:https://www.bilibili.com/video/BV1uT41177fX/?spm_id_from=333.788&vd_source=ddffd51aa532d23e6feac69924e20891
在这里插入图片描述
在这里插入图片描述

解法一:String类的 lastIndexOf() 方法

思路:利用String类的 lastIndexOf() 方法,将最后一个无空格字符串添加到新字符串中。

    public String reverseWords(String s) {
        //去除前导空格和尾随空格
        s = s.trim();

        StringBuffer result = new StringBuffer();
        int i = s.lastIndexOf(' ');
        while(i!=-1){
            result.append(s.substring(i+1,s.length())+" ");
            s = s.substring(0,i);
            //排除连续空格的干扰
            s = s.trim();
            i = s.lastIndexOf(' ');
        }
        //添加最开头的无空格字符串到新字符串末尾
        result.append(s);
        return result.toString();
    }

解法二:字符串整体翻转后,逐个单词翻转

如果字符串是可变数据类型,则能使得空间复杂度为O(1)。
这里给出本解法锻炼思维。

    public String reverseWords(String s) {
        //去除空格
        char[] ch = removeSpace(s);
        // System.out.println(ch);
        //字符数组整体翻转
        ch = reverseString(ch,0,ch.length-1);
        // System.out.println(ch);
        //翻转单个单词
        ch = reverseEachWord(ch);
        // System.out.println(ch);
        return new String(ch);
    }
	//视频中去空格方法
    public char[] removeSpace(String s){
        char[] ch = s.toCharArray();
        int slow=0;
       for(int fast=0;fast<s.length();fast++){
            if(ch[fast]!=' '){
                if(slow!=0){
                    ch[slow]=' ';
                    slow++;
                }
                while(fast < s.length() && ch[fast]!=' '){
                    ch[slow] = ch[fast];
                    slow++;
                    fast++;//这里自增之后fast指向一个空字符" "
                    //外层for循环再次自增会跳过对于该字符串的判断
                }
            }
        }
        char[] res = new char[slow];
        for(int i=0;i<slow;i++){
            res[i] = ch[i];
        }
        return res;
    }
    //自己写的去空格方法(更容易理解)
    // public String reverseWords(String s) {
    //     char[] ch = s.toCharArray();
    //     int slow=0,fast=0;
    //     while(fast<s.length()){
    //         if(ch[fast]!=' '){
    //             ch[slow] = ch[fast];
    //             fast++;
    //             slow++;
    //         }else{   // ch[fast]==' '
    //             while(ch[fast]==' '){
    //                 fast++;
    //             }
    //             ch[slow] = ' ';
    //             slow++;
    //         }
    //     }
    //     char[] res = new char[slow];
    //     for(int i=0;i<slow;i++){
    //         res[i] = ch[i];
    //     }
    //     return new String(res);
    // }

    public char[] reverseString(char[] ch,int start,int end){
        int l=start,r=end;
        while(l<r){
            char temp = ch[r];
            ch[r] = ch[l];
            ch[l] = temp;
            l++;
            r--;
        }
        return ch;
    }
    public char[] reverseEachWord(char[] ch){
        int start = 0;
        for(int i=0; i<ch.length; i++){
            if(ch[i]==' '){
                reverseString(ch,start,i-1);
                start = i+1;
            }
        }
        reverseString(ch,start,ch.length-1);
        return ch;
    }


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

教程:https://programmercarl.com/%E5%89%91%E6%8C%87Offer58-II.%E5%B7%A6%E6%97%8B%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC
在这里插入图片描述

解法一:String类的 substring() 方法

    public String reverseLeftWords(String s, int n) {
        return s.substring(n,s.length())+s.substring(0,n);
    }

解法二:三次翻转

若String可变,则不需要申请额外空间,只在本串上操作。
不适合使用java做,主要领会其方法。

    public String reverseLeftWords(String s, int n) {
        //不申请额外空间,只在本串上操作。
        //先整体翻转
        String s1 = reverse(s);
        //翻转后n个字符
        String s2 = reverse(s1.substring(s1.length()-n));
        //翻转前面的字符
        String s3 = reverse(s1.substring(0,s1.length()-n));
        return s3+s2;
    }

    public String reverse(String s){
        char[] str = s.toCharArray();
        int i=0,j=str.length-1;
        while(i<j){
            str[i]^=str[j];
            str[j]^=str[i];
            str[i]^=str[j];
            i++;
            j--;
        }
        return new String(str);
    }

总结

1、java字符串不可变,若向使用指针,需要先使用 toCharArray()方法 转换成字符数组chart[]。
2、寻找特定字符的索引可使用 StringBuilder(高效线程不安全)或者StringBuffer(线程安全)
3、截取子字符串可使用String类的 substring()方法(注意方法名全小写),此操作时间复杂度为O(n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值