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

Leetcode 344.反转字符串

题目链接
思路:利用两个指针交换前后对元素,这里有一个异或对方法,也比较简单,下面直接看代码。
代码

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--;
//        }
        // 方法二
        //首先 ^是位异或运算,对应的二进制位同为0或同为1 结果为0。
        //比如 a = 2 b = 1 对应的二进制为a = 10 b = 01 ,^异或操作
        //所以 a ^= b 即 a = a^b 也就是 10^01 = 11 a变成11
        //b ^= a 即 b = b^a 也就是 01^11= 10 b变成 10    即 b = b^(a^b) = a
        //a ^= b 即 a = a^b 也就是 11^10 = 01 a变为01    即 a = (a^b)^b = b
        //a和b完成交换。
        int left = 0;
        int right = s.length - 1;
        while (left < right) {
            // a ^= b 即 a = a^b 也就是 10^01 = 11 a变成11
            s[left] ^= s[right];
            // b ^= a 即 b = b^a 也就是 01^11= 10 b变成 10    即 b = b^(a^b) = a
            s[right] ^= s[left];
            // a ^= b 即 a = a^b 也就是 11^10 = 01 a变为01    即 a = (a^b)^b = b
            s[left] ^= s[right];
            left++;
            right--;
        }
    }
}

Leetcode 541. 反转字符串II

题目链接
思路:直接按题意进行模拟:反转每个下标从2k的倍数开始的、长度为k的子串,若该子串长度不足k,则反转整个子串。
代码

class Solution {
    public String reverseStr(String s, int k) {
        int n = s.length();
        char[] arr = s.toCharArray();
        for (int i = 0; i < n; i += 2 * k) {
            // 反转每个下标从2k的倍数开始的、长度为k的子串,若该子串长度不足k,则反转整个子串。
            reverse(arr, i, Math.min(i + k, n) - 1);
        }
        return new String(arr);
    }

    private void reverse(char[] arr, int left, int right) {
        while (left < right) {
            arr[left] ^= arr[right];
            arr[right] ^= arr[left];
            arr[left] ^= arr[right];
            left++;
            right--;
        }
    }
}

Leetcode 剑指Offer 05.替换空格

题目链接
思路:双指针法
代码

class Solution {
    public String replaceSpace(String s) {
        if (s == null || s.length() == 0) {
            return s;
        }
        // 扩充空间,空格数量x2
        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 left = s.length() - 1;
        // 扩充字符串s的大小,也就是每个空格替换成"%20"之后的大小
        s += sb.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);
    }
}

时间复杂度:O(n)
空间复杂度:O(n),使用StringBuilder开辟了新空间。

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

题目链接
思路

  1. 去除首尾以及中间多余空格
  2. 反转整个字符串
  3. 反转各个单词

代码

class Solution {
    /**
     * 1.去除首尾以及中间多余空格
     * 2.反转整个字符串
     * 3.反转各个单词
     */
    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);
            // 这里指如果sb的末尾已经是空格了,如果还有空格,则不加入空格
            if (c != ' ' || sb.charAt(sb.length() - 1) != ' ') {
                sb.append(c);
            }
            start++;
        }
        return sb;
    }

    private 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;
        }
    }
}

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

题目链接
思路:先整个字符串反转,再反转前面的,最后反转后面n个
代码

class Solution {
    public String reverseLeftWords(String s, int n) {
        // 用原始数组来进行操作,使其空间复杂度降为O(1)
        char[] chars = s.toCharArray();
        // 1.先反转整个字串
        reverse(chars, 0, chars.length - 1);
        // 2.再反转前面的
        reverse(chars, 0, chars.length - 1 - n);
        // 3.最后反转后面n个
        reverse(chars, chars.length - n, chars.length - 1);
        return new String(chars);
    }

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

你可能感兴趣的:(代码随想录算法训练营,算法,leetcode,数据结构,java)