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

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

继续补打卡,补博客。。。。

344. 反转字符串

在这里插入图片描述
有库函数的语言,一行代码reverse就完事。。。或者直接切片倒过来就行
当然如果真直接用库函数那么做本题就失去其意义了,这里还是不用库函数去实现
双指针思路,左右指针向中间靠齐,交换左右指针(没看题解直接就秒写出来的,一次就ac没有debug有点受宠若惊。。。)

java没有swap可以用只能自己实现

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

swap用异或实现

class Solution {
    public void reverseString(char[] s) {
        int l = 0;
        int r = s.length - 1;
        while (l < r) {
            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 完成交换
            l++;
            r--;
        }
    }
}

541. 反转字符串II

在这里插入图片描述
最近写模拟题都很抽象,自己的思路总是非常奇特罗嗦,都调用了库函数去实现反转写出来的代码还那么复杂
自己第一次写的版本:

class Solution {
    public String reverseStr(String s, int k) {
        StringBuilder sb ;
        StringBuilder resSb = new StringBuilder();
        ArrayList<String> res = new ArrayList<>();
        int len = s.length();
        int end  = 0;;
        for(int i = 0; i < len; i+= (2*k)){
            if(i + (2*k) > len) break;
            end = i + (2*k);
            sb = new StringBuilder(s.substring(i, i + k));
            res.add(sb.reverse().toString());
            res.add(s.substring(i + k, end));
        }
        System.out.println(res.toString());
        int lastLen = len - end;
        if(lastLen < k){
            sb = new StringBuilder(s.substring(end));
            res.add(sb.reverse().toString());
        }else if (lastLen < 2*k && lastLen >= k){
            sb = new StringBuilder(s.substring(end,end + k));
            res.add(sb.reverse().toString());
            res.add(s.substring(end + k));
        }
 
        for(String str : res){
            resSb.append(str);
        }
        return resSb.toString();
    }

}

双指针实现翻转,然后模拟过程
看题解后重写的:

class Solution {
    public String reverseStr(String s, int k) {
        char[] ch = s.toCharArray();
        int len = s.length();
        for(int i = 0; i < s.length(); i+=(2*k)){
            if(len - i < k){
                reverseCh(ch,i,len - 1);
            }else {
                reverseCh(ch,i,i + k -1);
            }
        }
        return String.valueOf(ch);
    }
    public void reverseCh(char[] ch, int l ,int r){
        while(l < r){
            char temp = ch[l];
            ch[l] = ch[r];
            ch[r] = temp;
            l++;
            r--;
        }
    }
}

剑指 Offer 05. 替换空格

在这里插入图片描述
调用库函数split一行代码AC

class Solution {
    public String replaceSpace(String s) {
        return s.replace(" ","%20");
    }
}

当然这样没啥意义,还是自己模拟实现。不过也还是简单,遍历遇到空格时加一个%20就可以了
java中的string不允许更改,所以只能借助StringBuilder

class Solution {
    public String replaceSpace(String s) {
       StringBuilder sb = new StringBuilder();
       for(int i =0; i < s.length(); i++){
           if(s.charAt(i) == ' '){
               sb.append("%20");
               continue;
           }
           sb.append(s.charAt(i));
       }
       return sb.toString();
    }
}

151. 反转字符串中的单词

在这里插入图片描述
java中String不可变,没法用O(1)原地修改

1、使用split解决:

string类的split方法的使用

split() 方法根据匹配给定的正则表达式来拆分字符串。
注意: . 、 $、 | 和 * 等转义字符,必须得加 \。
注意:多个分隔符,可以用 | 作为连字符。

public String[] split(String regex, int limit)

以一个空格分割:

	str.split("\\s");

以多个空格分割:

	str.split("\\s+");

本题代码:

class Solution {
    public String reverseWords(String s) {
        List<String> list = Arrays.asList(s.trim().split("\\s+"));
        Collections.reverse(list);
       return String.join(" ",list);
    }
}

2、不用split解决,双指针解法:
来源于力扣题解:

class Solution {
    public String reverseWords(String s) {
        char[] charArray=s.toCharArray();
        int left=0,right=s.length()-1;
        // 清除字符串两边的空格
        // 清除左边
        while(charArray[left]==' '){
            left++;
        }
        // 清除右边
        while(charArray[right]==' '){
            right--;
        }
        StringBuilder sb=new StringBuilder();
        // 开始添加单词
        while(left<=right){
            int index=right;
            // index 向左遍历找到第一个空格
            while(index>=left&&charArray[index]!=' '){
                index--;
            }
            // 现在 index 已经找到第一个空格,i=index+1 后移到字符串出现的位置
            // 添加字符串
            for(int i=index+1;i<=right;i++){
                sb.append(charArray[i]);
            }
            // 如果不是最后一个单词,就添加空格
            if(index>left) sb.append(' ');

            // 使用 index 指针 跳过中间可能出现的空格
            while(index>=left&&charArray[index]==' '){
                index--;
            }
            // 把 right 放到下一个单词出现的位置,继续循环
            right=index;
        }
        return sb.toString();

    }
}

剑指 Offer 58 - II. 左旋转字符串

在这里插入图片描述
用库函数substring

class Solution {
    public String reverseLeftWords(String s, int n) {
        StringBuilder  sb = new StringBuilder();
        sb.append(s.substring(n)).append(s.substring(0,n));
        return sb.toString();
    }
}

为了让本题有点难度,不调用库函数,不借助新的字符串解决
实现reverse函数,然后:

1. 先把第一个区间反转,再把第二个区间反转
2. 再把整体反转

感觉这种做法自己挺难想得到

class Solution {
    public String reverseLeftWords(String s, int n) {
        StringBuilder sb = new StringBuilder(s);
        sb = reverseStr(sb , 0 , n - 1 );
        sb = reverseStr(sb , n , s.length() - 1);
        sb = reverseStr(sb , 0 , s.length() - 1);
        return sb.toString();

    }
    public StringBuilder reverseStr(StringBuilder sb , int l ,int r){
        while(l < r){
            char temp = sb.charAt(l);
            sb.setCharAt(l,sb.charAt(r));
            sb.setCharAt(r,temp);
            l++;
            r--;
        }
        return sb;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值