代码随想录算法训练营 DAY8 | 344.反转字符串 541.反转字符串II 卡码网54.替换数字 151.反转字符串中的单词 卡码网55.右旋字符串

本文介绍了Java中字符串的不可变性,使用StringBuilder进行可变操作,以及如何处理字符串反转(包括LeetCode题目344和541)、去除多余空格和单词反转的算法。涉及的方法有StringBuilder的append、charAt,以及双指针技巧的应用。
摘要由CSDN通过智能技术生成

java中的字符串

  1. **String不能修改!!**要修改只能用StringBuilder!
sb.apppend();
  1. 字符串相关方法

字符串长度是str.length()

str.charAt()

构造方法传char数组:new String(chars)

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

344.反转字符串

题目链接:https://leetcode.cn/problems/reverse-string/

视频链接:https://www.bilibili.com/video/BV1fV4y17748/?spm_id_from=333.788&vd_source=80cf8293f27c076730af6c32ceeb2689

讲解链接:https://programmercarl.com/0344.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2.html

双指针

也是用双指针,一个从头,一个从尾,在中间汇合。每交换一次i++,j–。

while(i < j) 当i=j时不需要交换了,因此不写等号。

在这里插入图片描述

swap方法实现

swap可以有两种实现。

  • 一种就是常见的交换数值:
int tmp = s[i];
s[i] = s[j];
s[j] = tmp;
  • 一种就是通过位运算:
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
class Solution {
    public void reverseString(char[] s) {
        int i = 0;
        int j = s.length-1;
        while(i < j) {
            char tmp = s[i];
            s[i] = s[j];
            s[j] = tmp;
            i++;
            j--;
        }
    }
}

541.反转字符串II

题目链接:https://leetcode.cn/problems/reverse-string-ii/description/

视频链接:https://www.bilibili.com/video/BV1dT411j7NN/?spm_id_from=333.788&vd_source=80cf8293f27c076730af6c32ceeb2689

讲解链接:https://programmercarl.com/0541.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2II.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE

思路

修改循环遍历,不要用i++,这里改成每次步进2k个。

for(int i = 0;i < len; i += 2*k)

注意reverse函数里是左闭右闭的!

class Solution {
    public void reverse(char[] s, int i, int j) {
        while(i < j) {
            char tmp = s[i];
            s[i] = s[j];
            s[j] = tmp;
            i++;
            j--;
        }
    }

    public String reverseStr(String s, int k) {
        char[] chars = s.toCharArray();
        int cnt = 0;
        int len = chars.length;
        for(int i = 0; i < len; i+=2*k) { //每次步进2k,翻转前k个
            int rem = len - i;
            if(rem < k) {
                reverse(chars, i ,len-1);
                break;
            }
            if(rem >= k && rem < 2*k) {
                reverse(chars,i,i+k-1);
                break;
            }
            reverse(chars,i,i+k-1);
        }
        String result = new String(chars);
        return result;
    }
}

卡码网54.替换数字

c++的做法是扩容数组,为替换成number预留出空间,然后从后向前覆盖。

java因为String不能变,只能另外开一个sb,遍历s的同时,动态append到sb后面。

是数字就append("number"),不是就append(s.charAt(i))

判定是不是数字用Character.isDigit()

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            if (Character.isDigit(s.charAt(i))) {
                sb.append("number");
            }else sb.append(s.charAt(i));
        }
        System.out.println(sb);
    }
}

151.反转字符串中的单词

思路

要求:空间O(1),不用库函数

不仅要去除首尾的空格,还要去除重复的空格。

整体思路:先整体反转,再反转每一个单词

  1. 先将整体字符串反转了。eg:he__wo (_代表空格)

  2. 反转后变成:ow__eh,单词内部没转过来,再针对每一个单词做反转。

  3. 最后变成:wo__he,就是结果了!!!

  • 总体逻辑
public String reverseWords(String s) {
        char[] c = s.toCharArray();
        c = deleteExtraSpaces(c);
        //先整体反转一下    
        reverse(c,0,c.length-1);
        //然后反转每个单词:
        reverseEachWord(c);
        return new String(c);
    }

  • 怎么删除多余的空格?

回忆数组中的移除元素那题,这里我们移除的就是空格元素。这里是在原地操作!!

定义快慢指针,快指针用来指向符合的字符,慢指针用来指向快指针更新的字符应该更新在哪里。

特殊处理首个单词不留空格,if(slow!=0) s[slow++]=' '

public char[] deleteExtraSpaces(char[] s) {
        //快慢指针移除首尾和多余的空格
        int slow = 0; //慢指针负责指定符合的元素要放的位置
        for(int i = 0; i < s.length; i++) {
            if(s[i] != ' ') {  //遇到不为空格的才处理 为空格就跳过
                if(slow != 0) {  //如果第一个字符是单词,就不手动加空格了
                    //进到这里说明:1.s[slow]不是空格 2.不是第一个单词。要手动加一个空格
                    s[slow++] = ' ';
                }
                while(i < s.length && s[i]!=' '){  //在while里把快指针找到的单词一个个移动过来
                    s[slow++] = s[i++];
                }  
            } 
        }
    	//后面的相当于cpp里的resize,重新开一个空间合适的新数组
    
        char[] newChars = new char[slow];
        System.arraycopy(s, 0, newChars, 0, slow); 
        return newChars;
    }

在这里插入图片描述


  • 单个单词反转的方法逻辑
public void reverseEachWord(char[] c) {
        int start = 0; //存储每个单词的开始位置
        for(int i = 0; i <= c.length; i++){
            if(i == c.length || c[i] == ' ') {  //如果i到了末尾或者到了空格,就说明找到了一整个单词[start,i-1]
                reverse(c,start,i-1);
                start = i+1;//更新start,指向下一个单词的开始位置
            }
        }
    }

注意判断是否到了末尾或空格那里,用||连接,而且要先判断i==c.length,否则会越界!!

reverse传参是左闭右开,进到if了就说明此时i指向空格或者末尾(下标是length)

  • java代码
class Solution {
    //反转,左闭右闭
    public void reverse(char[] s, int i, int j) {
        while(i < j) {
            char tmp = s[i];
            s[i] = s[j];
            s[j] = tmp;
            i++;
            j--;
        }
    }

    public char[] deleteExtraSpaces(char[] s) {
        //快慢指针移除首尾和多余的空格
        int slow = 0; //慢指针负责指定符合的元素要放的位置
        for(int i = 0; i < s.length; i++) {
            if(s[i] != ' ') {  //遇到不为空格的才处理 为空格就跳过
                if(slow != 0) {  //如果要放的位置是第一个,就不手动加空格了
                    //进到这里说明:1.s[slow]不是空格 2.不是第一个单词。要手动加一个空格
                    s[slow++] = ' ';
                }
                while(i < s.length && s[i]!=' '){  //在while里把快指针找到的单词一个个移动过来
                    s[slow++] = s[i++];
                }  
            } 
        }
        char[] newChars = new char[slow];
        System.arraycopy(s, 0, newChars, 0, slow); 
        return newChars;
    }

    public void reverseEachWord(char[] c) {
        int start = 0; //存储每个单词的开始位置
        for(int i = 0; i <= c.length; i++){
            if(i == c.length || c[i] == ' ') {  //如果i到了末尾或者到了空格,就说明找到了一整个单词[start,i-1]
                reverse(c,start,i-1);
                start = i+1;//更新start,指向下一个单词的开始位置
            }
        }
    }

    public String reverseWords(String s) {
        char[] c = s.toCharArray();
        c = deleteExtraSpaces(c);
        //先整体反转一下    
        reverse(c,0,c.length-1);
        //然后反转每个单词:
        reverseEachWord(c);
        return new String(c);
    }
}

卡码网55.右旋字符串

题目链接:https://kamacoder.com/problempage.php?pid=1065

讲解链接:https://programmercarl.com/kama55.%E5%8F%B3%E6%97%8B%E5%AD%97%E7%AC%A6%E4%B8%B2.html#%E6%80%9D%E8%B7%AF

在这里插入图片描述

负负得正,先反转前一段[0,k-1]子串 在反转后一段[k,len-1]。

最后反转整个串[0,len-1]

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = Integer.parseInt(in.nextLine());
        String s = in.nextLine();

        int len = s.length();  //获取字符串长度
        char[] chars = s.toCharArray();
        reverseString(chars, 0, len - 1);  //反转整个字符串
        reverseString(chars, 0, n - 1);  //反转前一段字符串,此时的字符串首尾尾是0,n - 1
        reverseString(chars, n, len - 1);  //反转后一段字符串,此时的字符串首尾尾是n,len - 1
        
        System.out.println(chars);

    }

    public static void reverseString(char[] ch, int start, int end) {
        //异或法反转字符串,参照题目 344.反转字符串的解释
        while (start < end) {
            ch[start] ^= ch[end];
            ch[end] ^= ch[start];
            ch[start] ^= ch[end];
            start++;
            end--;
        }
    }
}

day8总结

  1. java中String是不可变的。可以考虑新建一个StringBuilder然后用append拼接,或者用toCharArray方法转化成char数组再进行操作。最后返回的时候return new String(chars)
  2. 左旋/右旋字符串:先整体反转,再分别反转左半部分和右半部分即可
  3. swap方法可以用tmp或者位运算实现。注意是左闭右闭
  4. 去除一个字符串中多余空格的逻辑比较复杂,回顾移除数组那道题里的实现,用快慢指针,slow指向符合的元素要放的位置,fast指针遍历整个串 去找不为空格的字符。放完一个单词之后要手动添加一个空格(注意首个字符的情况 不用放)
  5. 已经去掉多余空格之后,寻找单个的单词也是用双指针,start记录一个单词的起始位置,i去找结束位置,一旦为空格就停下,此时reverse(start,i-1).然后start更新成i+1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值