算法DAY8 | 344.反转字符串 / 541.反转字符串II / 剑指Offer 05.替换空格 / 151.翻转字符串里的单词 / 剑指Offer 58-II.左旋转字符串

344.反转字符串

题目链接

  • 标签:字符串
  • 难度:4.0

跟反转数组没区别。

提供了两种方法,区别在于交换的实现。

方法一:临时变量(常用)
public void reverseString(char[] s) {
    char temp;
    int left = 0;
    int right = s.length - 1;
    while(right > left){
        temp = s[left];
        s[left++] = s[right];
        s[right--] = temp;
    }
}
方法二:位运算(了解)
public void reverseString(char[] s) {
    int left = 0;
    int right = s.length - 1;
    while (right > left) {
        s[left] ^= s[right];  //构造 a ^ b 的结果,并放在 a 中
        s[right] ^= s[left];  //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b
        s[left++] ^= s[right--];  //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换
    }
}

541.反转字符串II

题目链接

  • 标签:字符串
  • 难度:5.0

相比上一道题,这道明显麻烦了点,但基本思想还是手动模拟,没有什么巧解。

public String reverseStr(String s, int k) {
    // 这步很重要,把字符串转为字符数组,在java里更好处理
    char[] s1 = s.toCharArray();
    
    // 一开始把左右指针定在前k个元素
    int left = 0;
    int right = k-1;
    
    // 如果一共都没有k个元素,把右指针调整到最后一个元素处
    if(right >= s1.length){
        right = s1.length - 1;
    }
    
    // 外层循环:每2k个元素循环一次
    while(true){
        // 因为左右指针在交换过程中会动,所以要用临时变量保存起来
        int tempLeft = left;
        int tempRight = right;
        
        // 和上道题一样的交换过程
        while(left < right) {
            char temp;
            temp = s1[right]; 
            s1[right--] = s1[left];
            s1[left++] = temp;
        }
        
        // 改变左右指针的位置到下一个区间
        left = tempLeft + 2*k;
        right = tempRight + 2*k;
        // 左指针都超了,说明不需要再交换了
        if(left > s1.length) break;
        
        // 如果左指针没超,右指针超了,说明剩下不到k个元素,就把右指针调到最后一个元素处
        if(right > s1.length){
            right = s1.length - 1;
        }
    }
    // 别忘了恢复成字符串,String类的构造函数可以直接传入字符数组!
    return new String(s1);
}

剑指Offer 05.替换空格

题目链接

  • 标签:字符串
  • 难度:5.0

借助Java的StringBuilder类直接开辟新的数组,这个题可以说是非常之简单。

但还是要重点关注一下双指针解法,可以在原数组(字符串)上扩容,而不用开新数组。具体是数有多少空格,将原数组扩容空格个数的2倍,然后快指针从后往前遍历原数组,慢指针在后面按顺序填坑。快指针遇到空格,慢指针依次填入“0”、“2”、“%”;快指针遇到非空格元素,慢指针就填这个元素。

所以和27.移除元素很像!

请添加图片描述

方法一:StringBuilder
//使用一个新的对象,复制 str,复制的过程对其判断,是空格则替换,否则直接复制,类似于数组复制
public static String replaceSpace(String s) {
    if (s == null) {
        return null;
    }
    //选用 StringBuilder 单线程使用,比较快,选不选都行
    StringBuilder sb = new StringBuilder();
    //使用 sb 逐个复制 s ,碰到空格则替换,否则直接复制
    for (int i = 0; i < s.length(); i++) {
        //s.charAt(i) 为 char 类型,为了比较需要将其转为和 " " 相同的字符串类型
        //if (" ".equals(String.valueOf(s.charAt(i)))){}
        if (s.charAt(i) == ' ') {
            sb.append("%20");
        } else {
            sb.append(s.charAt(i));
        }
    }
    return sb.toString();
}
方法二:双指针(重要)
public String replaceSpace(String s) {
    if(s == null || s.length() == 0){
        return s;
    }
    //扩充的空间=空格数量2倍
    StringBuilder str = new StringBuilder();
    for (int i = 0; i < s.length(); i++) {
        if(s.charAt(i) == ' '){
            str.append("  ");
        }
    }
    //若是没有空格直接返回
    if(str.length() == 0){
        return s;
    }
    //有空格情况 定义两个指针
    int left = s.length() - 1;//左指针:指向原始字符串最后一个位置
    s += str.toString();
    int right = s.length()-1;//右指针:指向扩展字符串的最后一个位置
    char[] chars = s.toCharArray();
    while(left>=0){
        if(chars[left] == ' '){
            chars[right--] = '0';
            chars[right--] = '2';
            chars[right] = '%';
        }else{
            chars[right] = chars[left];
        }
        left--;
        right--;
    }
    return new String(chars);
}

这个题还要注意健壮性,一个是数组为空或者为null,另一个容易遗忘,就是遍历完了发现原字符串里没有空格,这样要直接返回原字符串


151.翻转字符串里的单词

题目链接

  • 标签:字符串、双指针
  • 难度:6.5

这个题很精彩,解法比较多,也比较复杂。

关注后续更新。


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

题目链接

  • 标签:字符串、双指针
  • 难度:5.0

很巧妙的思想,精华就三行代码,不多说了。

public String reverseLeftWords(String s, int n) {
    // 精华在此↓↓↓
    s = reverse(s,0,n-1);
    s = reverse(s,n,s.length()-1);
    s = reverse(s,0,s.length()-1);
    
    return s;
}

// 和上面第一题一样的反转操作
public String reverse(String s, int left, int right){
    char[] s1 = s.toCharArray();
    while(left < right){
        char temp;
        temp = s1[left];
        s1[left++] = s1[right];
        s1[right--] = temp;
    }
    return new String(s1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值