day08 打卡344.反转字符串 剑指Offer 05.替换空格 151.翻转字符串里的单词 剑指Offer58-II.左旋转字符串

day08 打卡344.反转字符串 剑指Offer 05.替换空格 151.翻转字符串里的单词 剑指Offer58-II.左旋转字符串

344.反转字符串

344题目链接

1.看到不创建新的空间,就自然想到了下面的代码。

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

541. 反转字符串II

541题目链接

1.自己的思路:每次遍历到2k*n个,处理2k范围内的反转。循环结束后,再处理剩余的字符串。剩余的字符串有两种情况:

剩下字符<k,全部反转,right就是最后一个字符;

剩下字符>k,前k个反转,right就是left+k-1;

class Solution {
    public String reverseStr(String s, int k) {
        int i = 2*k;
        int left = 0;
        int right = 0;
        char[] str = s.toCharArray();
        for ( ; i<str.length ; i = i+2*k) {
            left = i-2*k;
            right = i-k-1;
            str = reserve(str, left, right);
        }
        // 剩下的字符串处理,剩下的字符串肯定<2k
        left = i-2*k;
        if (str.length-left<k) {
            // 剩下字符<k,全部反转
            right = str.length-1;
            str = reserve(str, left, right);
        } else {
            // 剩下字符>k,前k个反转
            right = left+k-1;
            str = reserve(str, left, right);
        }
        
        return new String(str);
    }

    public char[] reserve(char[] str, int left, int right) {
        for (; left<=right ; left++, right--) {
            char temp = str[right];
            str[right] = str[left];
            str[left] = temp;
        }
        return str;
    }
}

2.看来代码随想录的视频,代码简洁了很多。不一样的思路,可以去看看视频

class Solution {
    public String reverseStr(String s, int k) {
        char[] str = s.toCharArray();
        for (int i = 0 ; i<str.length ; i = i+2*k) {
            // 满足大于或等于 k 个
            if (i+k <= str.length) {
                str = reserve(str, i, i+k-1);
                continue;
            }
            // 处理剩余字符少于 k 个
            str = reserve(str, i, str.length-1);
        }
        return new String(str);
    }

    public char[] reserve(char[] str, int left, int right) {
        for (; left<=right ; left++, right--) {
            char temp = str[right];
            str[right] = str[left];
            str[left] = temp;
        }
        return str;
    }
}

剑指Offer 05.替换空格

Offer 05题目链接

1.最容易想到的

class Solution {
    public String replaceSpace(String s) {
        String result = "";
        for (int i = 0 ; i<s.length() ; i++) {
            char c = s.charAt(i);
            if (c == ' ') {
                result += "%20";
            } else {
                result += c;
            }
        }
        return result;
    }
}

2.看了视频,使用双指针的办法。先扩容(注意这里是找到的空格数量乘以2,我一开始写成了3)。再判断遇到的是否为空格。如果是空格,右指针-3,赋值% 2 0;否则,右指针-1,正常赋值。left每次都-1。

class Solution {
    public String replaceSpace(String s) {
        int count = 0;
        for (int i = 0 ; i<s.length() ; i++) {
            if (s.charAt(i) == ' ') {
                count++;
            } 
        }
        if (count == 0) return s;
        char[] str = new char[s.length() + 2*count];
        int left = s.length()-1;
        int right = str.length-1;
        while(left>=0) {
            char c = s.charAt(left);
            if (c == ' ') {
                str[right] = '0';
                str[right-1] = '2';
                str[right-2] = '%';
                right = right-3;
            } else {
                str[right] = c;
                right--;
            }
            left--;
        }
        return new String(str);
    }
}

151.翻转字符串里的单词

151题目链接

1.反向遍历字符串。每当第一次遇到空格的时候,就说明了可以加入新的字符串了,字符串清空。如果连续空格,就continue,接着下次。

首先要把字符串的两端如果有空格,清空。所以i=0或者n-1的时候,都肯定不会是空格。空格最大就是n-2,最小就是1。

因为我们是倒着的,

怎么判断第一个空格呢?就是当前的等于空格并且前一个不是空格。

怎么判断是连续空格呢?先保证当前的是空格,后面的也等于空格就是需要跳过的。

class Solution {
    public String reverseWords(String s) {
        s = s.trim();
        if (s == null || s.length() == 0) return s;
        StringBuilder result = new StringBuilder();
        String str = "";
        for (int i = s.length()-1 ; i>=0 ; i--) {
            char c = s.charAt(i);
            if (i == 0 || (c == ' ' && s.charAt(i+1) != ' ')) {
                if (i == 0) {
                    str = c + str;
                } else {
                    str += " ";
                }
                result.append(str);
                str = "";
                continue;
            }
            if (c == ' ' && s.charAt(i+1) == ' ') {
                continue;
            } 

            str = c + str;
        }
        return result.toString();
    }
}

2.看了代码随想录的修改

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

    public StringBuilder removeSpace(String s) {
        int left = 0;
        int right = s.length()-1;
        StringBuilder sb = new StringBuilder();
        while (s.charAt(left) == ' ') left++;
        while (s.charAt(right) == ' ') right--;
        while (left<=right) {
            char c = s.charAt(left);
            if (c == ' ' &&  s.charAt(left-1) == ' ') {
                left++;
                continue;
            }
            sb.append(c);
            left++;
        }
        return sb;
    }

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

    // 反转字符串指定区间[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--;
        }
    }
}

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

Offer 58题目链接

1.不能申请额外空间的办法想不到,看了代码随想录的。

具体步骤为:

  1. 反转区间为前n的子串
  2. 反转区间为n到末尾的子串
  3. 反转整个字符串
class Solution {
    public String reverseLeftWords(String s, int n) {
        StringBuilder sb = new StringBuilder(s);
        // 1. 反转前n个字母
        reverseString(sb, 0, n-1);
        // 2. 反转n到末尾的字母
        reverseString(sb, n, s.length()-1);
        // 3. 全部反转
        reverseString(sb, 0, s.length()-1);
        return sb.toString();
    }

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

}

参考资料

代码随想录

posted @ 2023-03-08 16:07  zzzzzzsl  阅读(19)  评论(0)    收藏  举报