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

知识点

字符串也是一种数组,在算法方面,二者类似。

Leetcode 344. 反转字符串

题目链接:344. 反转字符串

思路:

很基础的一道题。

解题:成功

代码实现

class Solution {
    public void reverseString(char[] s) {
        int n = s.length;
        for(int i = 0; i < n / 2; i++){
            char temp = s[i];
            s[i] = s[n-1-i];
            s[n-1-i] = temp;
        }
    }
}

Leetcode 541. 反转字符串 II

题目链接:541. 反转字符串 II

思路:

当需要固定规律一段一段去处理字符串的时候,要想想能否在for循环的表达式上做文章。

解题:成功

代码实现

class Solution {
    public String reverseStr(String s, int k) {
        char[] chs = s.toCharArray();
        int n = chs.length;
        for(int i = 0; i < n; i += 2 * k){
            int left = i;
            int right = i + k - 1;
            if(right < n){
                reverse(chs, left, right);
            }
            else{
                reverse(chs, left, n-1);
            }
        }
        // 或者 return new String(chs);
        return String.valueOf(chs);
    }

    public void reverse(char[] chs, int left, int right){
        while(left < right){
            char temp = chs[left];
            chs[left] = chs[right];
            chs[right] = temp;
            left++;
            right--;
        }
    }
}

Leetcode 剑指 Offer 05. 替换空格

题目链接:剑指 Offer 05. 替换空格

思路:

对于线性数据结构,填充或者删除,后序处理会高效的多。
很多数组填充类的问题,都可以先预先给数组扩容成带填充后的大小,然后在从后向前进行操作。这么做有两个好处:

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

解题:成功

代码实现

方法一

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

方法二

class Solution {
    public String replaceSpace(String s) {
        if(s == null || s.length() == 0){
            return s;
        }
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < s.length(); i++){
            if(s.charAt(i) == ' '){
                sb.append("  ");
            }
        }
        if(sb.length() == 0){
            return s;
        }
        int j = s.length() - 1;
        s += sb.toString();
        char[] chs = s.toCharArray();
        int i = chs.length - 1;
        for(; j < i; i--, j--){
            if(chs[j] == ' '){
                chs[i--] = '0';
                chs[i--] = '2';
                chs[i] = '%';
            }
            else{
                chs[i] = chs[j];
            }
        }
        return new String(chs);
    }
}

Leetcode 151. 翻转字符串里的单词

题目链接:151. 翻转字符串里的单词

思路:

之前做过类似的题,但是忘记思路了。看了之前的笔记后,尝试写了一下,自己写的对于空格的相关处理逻辑写得很复杂。
空格处理部分和 27.移除元素 的逻辑是一样的,本题是移除空格,而 27.移除元素 就是移除元素。

解题:失败

代码实现

class Solution {
    public String reverseWords(String s) {
        char[] chs = s.toCharArray();
        chs = removeExtraSpaces(chs);
        reverseString(chs, 0, chs.length - 1);
        reverseEachWord(chs);
        return new String(chs);
    }

    public char[] removeExtraSpaces(char[] chs){
        int slow = 0;
        for(int fast = 0; fast < chs.length; fast++){
            if(chs[fast] != ' '){
                if(slow != 0){
                    chs[slow] = ' ';
                    slow++;
                }
                while(fast < chs.length && chs[fast] != ' '){
                    chs[slow] = chs[fast];
                    slow++;
                    fast++; 
                }
            }
        }
        char[] newArr = new char[slow];
        for(int i = 0; i < slow; i++){
            newArr[i] = chs[i];
        }
        return newArr;
    }


    public void reverseString(char[] chs, int left, int right){
        while(left < right){
            char temp = chs[left];
            chs[left] = chs[right];
            chs[right] = temp;
            left++;
            right--;
        }
    }

    public void reverseEachWord(char[] chs){
        int start = 0;
        for(int end = 0; end <= chs.length; end++){
            if(end == chs.length || chs[end] == ' '){
                reverseString(chs, start, end - 1);
                start = end + 1;
            }
        }
    }
}

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

题目链接:剑指 Offer 58 - II. 左旋转字符串

思路:

之前看过一模一样的题(编程之美 2.17),但是没有自己写代码。忘记思路了。

解题:失败

代码实现

class Solution {
    public String reverseLeftWords(String s, int n) {
        char[] chs = s.toCharArray();
        reverse(chs, 0, n-1);
        reverse(chs, n, chs.length - 1);
        reverse(chs, 0, chs.length - 1);
        return new String(chs);
    }

    public void reverse(char[] chs, int left, int right){
        while(left < right){
            char temp = chs[left];
            chs[left] = chs[right];
            chs[right] = temp;
            left++;
            right--;
        }
    }

    // 另一种反转字符串的写法 
    // public void reverse(char[] chars, int left, int right) {
    //     while (left < right) {
    //         chars[left] ^= chars[right];
    //         chars[right] ^= chars[left];
    //         chars[left] ^= chars[right];
    //         left++;
    //         right--;
    //     }
    // }
}

总结

后面两题还是有点难想的,只能加深印象,死记了:

  1. 在 151. 翻转字符串里的单词 (opens new window) 中,要对一句话里的单词顺序进行反转,先整体反转再局部反转是一个很妙的思路。
  2. 剑指 Offer 58 - II. 左旋转字符串 则是先局部反转再整体反转,与 151. 翻转字符串里的单词 (opens new window) 类似,但是也是一种新的思路。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值