344. 反转字符串

位运算也可以实现,异或,不开空间进行交换

  1. class Solution {
  2. public void reverseString(char[] s) {
  3. int l = 0;
  4. int r = s.length - 1;
  5. while (l < r) {
  6. s[l] ^= s[r]; //构造 a ^ b 的结果,并放在 a 中
  7. s[r] ^= s[l]; //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b
  8. s[l] ^= s[r]; //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换
  9. l++;
  10. r--;
  11. }
  12. }
  13. }

541. 反转字符串 II

比我的解法好,因为剩下的最后部分的右指针的判断,也可以放到循环里

  1. public String reverseStr(String s, int k) {
  2. char[] ch = s.toCharArray();
  3. for(int i = 0; i < ch.length; i += 2 * k){
  4. int start = i;
  5. //这里是判断尾数够不够k个来取决end指针的位置
  6. int end = Math.min(ch.length - 1, start + k - 1);
  7. //用异或运算反转
  8. while(start < end){
  9. ch[start] ^= ch[end];
  10. ch[end] ^= ch[start];
  11. ch[start] ^= ch[end];
  12. start++;
  13. end--;
  14. }
  15. }
  16. return new String(ch);
  17. }

剑指 Offer 05. 替换空格

常规解法

  1. public String replaceSpace(String s) {
  2. if (s==null || s.length()==0)
  3. return s;
  4. StringBuilder sb = new StringBuilder();
  5. for (int i = 0; i < s.length(); ++i){
  6. char c = s.charAt(i);
  7. if (c == ' ') {
  8. sb.append("%20");
  9. }else{
  10. sb.append(c);
  11. }
  12. }
  13. return new String(sb);
  14. }

双指针

题目如果要求原地修改数组,空间复杂度为常数级

  1. public String replaceSpace(String s) {
  2. if(s == null || s.length() == 0){
  3. return s;
  4. }
  5. //扩充空间,新字符串比旧字符串多 空格数量的2倍
  6. StringBuilder str = new StringBuilder();
  7. for (int i = 0; i < s.length(); i++) {
  8. if(s.charAt(i) == ' '){
  9. str.append(" ");
  10. }
  11. }
  12. //若是没有空格直接返回
  13. if(str.length() == 0){
  14. return s;
  15. }
  16. //有空格情况 定义两个指针
  17. int left = s.length() - 1;//左指针:指向原始字符串最后一个位置
  18. s += str.toString();
  19. int right = s.length()-1;//右指针:指向扩展字符串的最后一个位置
  20. char[] chars = s.toCharArray();
  21. while(left>=0){
  22. if(chars[left] == ' '){
  23. chars[right--] = '0';
  24. chars[right--] = '2';
  25. chars[right] = '%';
  26. }else{
  27. chars[right] = chars[left];
  28. }
  29. left--;
  30. right--;
  31. }
  32. return new String(chars);
  33. }

151. 颠倒字符串中的单词

简单解法

  1. public String reverseWords(String s) {
  2. // 除去开头和末尾的空白字符
  3. s = s.trim();
  4. // 正则匹配连续的空白字符作为分隔符分割
  5. List<String> wordList = Arrays.asList(s.split("\\s+"));
  6. Collections.reverse(wordList);
  7. return String.join(" ", wordList);
  8. }

双指针

class Solution {
   /**
     * 不使用Java内置方法实现
     * <p>
     * 1.去除首尾以及中间多余空格
     * 2.反转整个字符串
     * 3.反转各个单词
     */
    public String reverseWords(String s) {
        // System.out.println("ReverseWords.reverseWords2() called with: s = [" + s + "]");
        // 1.去除首尾以及中间多余空格
        StringBuilder sb = removeSpace(s);
        // 2.反转整个字符串
        reverseString(sb, 0, sb.length() - 1);
        // 3.反转各个单词
        reverseEachWord(sb);
        return sb.toString();
    }

    private StringBuilder removeSpace(String s) {
        // System.out.println("ReverseWords.removeSpace() called with: s = [" + 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++;
        }
        // System.out.println("ReverseWords.removeSpace returned: sb = [" + sb + "]");
        return sb;
    }

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

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

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

简单解法1—直接拼串

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

简单解法2—取余

    public String reverseLeftWords(String s, int n) {
        s += s;
        return s.substring(n, s.length()/2);
    }

三次反转

class Solution {
    public String reverseLeftWords(String s, int n) {
        int len=s.length();
        StringBuilder sb=new StringBuilder(s);
        reverseString(sb,0,n-1);
        reverseString(sb,n,len-1);
        return sb.reverse().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--;
            }
        }
}