代码随想录算法训练营第八天| 344.反转字符串、541.反转字符串Ⅱ、剑指offer05.替换空格、151.反转字符串中的单词、剑指offer58.左旋字符串

344.反转字符串

思路:使用双指针完成就地逆置,思路和操作都比较简单

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

        while(left < right) {
            temp = s[right];
            s[right] = s[left];
            s[left] = temp;

            left++;
            right--;
        }
    }
}

541.反转字符串Ⅱ

思路:根据题目中规定的反转规则进行模拟。题目大意总体可以概括为:每隔2k个反转前k个,尾数不够k个时候全部反转。

class Solution {
    public String reverseStr(String s, int k) {

        char[] arr = s.toCharArray();
        for(int i = 0; i < arr.length; i += 2*k) {
                int start = i;

                int end = Math.min(arr.length - 1, start + k -1);

                while(start < end) {
                    char temp = arr[start];
                    arr[start] = arr[end];
                    arr[end] = temp;

                    start++;
                    end--;
                }
        }
        return new String(arr);
    }
}

小结:值得注意的点

  • 当需要固定规律一段一段去处理字符串的时候,要想想在for循环表达式上调整。利用i每次变化2k,即每循环一次便对2k个字符中的前k个字符反转。
  • end的取值需要好好思考,end的值每次和star+k-1的值进行比较并取最小,这样可以保证每次都能取到对应的边界值

剑指offer05.替换空格

思路:使用substring来拼接字符串或者双指针法。

用Java中substring()来进行字符串拼接

class Solution {
    public String replaceSpace(String s) {

        if (s.length() == 0) {
            return s;
        }
        
        int length = s.length();

        for(int i = 0; i < length;) {
            if(s.charAt(i) == ' ') {
                s = s.substring(0, i) + "%20" + s.substring(i+1, length);
                length = s.length();
                i += 3;
            } else {
                i++;
            }
        }

        if(s.charAt(0) == ' ') {
            s = "%20" + s.substring(1, length-1);
        } 

        if(s.charAt(length-1) == ' ') {
            s = s.substring(0, length-2) + "%20";
        }

        return s;
    }
}

小结:值得注意的点

  • 对字符串长度为0时的处理
  • 先处理两端内的空格,最后处理两端的空格

双指针法

class Solution {
    public String replaceSpace(String s) {

        if(s.length() == 0) {
            return s;
        }

        if(s.equals(" ")) {
            return "%20";
        }

        int num = 0; 

        for(int i = 0; i < s.length(); i++) {
            if(s.charAt(i) == ' ') {
                num++;
            }
        }

        char[] arr = new char[s.length()+2*num];
        int p = arr.length - 1;
        int q = s.length() - 1;

       while (q >= 0) {
            if(s.charAt(q) == ' ') {
                arr[p] = '0';
                arr[p-1] = '2';
                arr[p-2] = '%';
                p -= 3;
                q--;
            } else{
                arr[p] = s.charAt(q);
                p--;
                q--;
            }
        }
        return new String(arr);
    }
}

小结:值得注意的点

  • 先根据空格的数量来计算出新数组所需空间,记得要减掉空格的数量
  • 从新数组尾端开始香前不断插入原来字符串中的字符,遇到空格则插入%20
  • 对于字符串长度为0以及只包含一个空格的处理

151.反转字符串中的单词

思路:这道题综合了字符串的多种操作。首先考虑到要移除多余的空格,其次将整个字符串反转,最后将每个单词进行反转,便可以得到对应的结果。

class Solution {
    public String reverseWords(String s) {
        // 1.去除首尾以及中间多余空格
        StringBuilder sb = removeSpace(s);
        // 2.反转整个字符串
        reverseString(sb, 0, sb.length() - 1);
        // 3.反转各个单词
        reverseEachWord(sb);
        return sb.toString();
    }

    private StringBuilder removeSpace(String s) {
        int start = 0;
        int end = s.length() - 1;
        while (s.charAt(start) == ' ') start++;
        while (s.charAt(end) == ' ') end--;
        StringBuilder sb = new StringBuilder();
        while (start <= end) {
            char c = s.charAt(start);
            if (c != ' ' || sb.charAt(sb.length() - 1) != ' ') {
                sb.append(c);
            }
            start++;
        }
        return sb;
    }

    /**
     * 反转字符串指定区间[start, end]的字符
     */
    public void reverseString(StringBuilder sb, int start, int end) {
        while (start < end) {
            char temp = sb.charAt(start);
            sb.setCharAt(start, sb.charAt(end));
            sb.setCharAt(end, temp);
            start++;
            end--;
        }
    }

    private void reverseEachWord(StringBuilder sb) {
        int start = 0;
        int end = 1;
        int n = sb.length();
        while (start < n) {
            while (end < n && sb.charAt(end) != ' ') {
                end++;
            }
            reverseString(sb, start, end - 1);
            start = end + 1;
            end = start + 1;
        }
    }
}

小结:值得注意的点

  • 对首尾两端连续出现的空格的清除操作使用while

剑指offer58.左旋字符串

思路:方法一:利用Java中substring()来进行字符串拼接,方法二:整体反转+局部反转就可以实现反转单词顺序的目的。该题和151.反转字符串中的单词有异曲同工之妙,先整体反转,后局部反转等价于先局部反转,后整体反转。

用Java中substring()来进行字符串拼接

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

整体反转+局部反转

class Solution {
    public String reverseLeftWords(String s, int n) {
        char[] arr = s.toCharArray();

        reverse(arr, 0,n-1);
        reverse(arr, n, s.length() - 1);
        reverse(arr, 0, s.length() - 1);
        return new String(arr);
    }

    private void reverse(char[] arr, int left, int right) {

        char temp;

        while(left < right) {
            temp = arr[right];
            arr[right] = arr[left];
            arr[left] = temp;
            left++;
            right--;
        }
    }
}

小结:可以通过局部反转+整体反转 达到左旋转的目的

  1. 反转区间为前n的子串
  2. 反转区间为n到末尾的子串
  3. 反转整个字符串

值得注意的是对字符串数组中进行反转时边界位置的确定

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值