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

目录

344  反转字符串

541  反转字符串II

剑指Offer 05  替换空格

151  翻转字符串里的单词

剑指Offer58-II  左旋转字符串


344  反转字符串

题目链接

代码随想录day08| 344.反转字符串、541. 反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串_第1张图片

看到题目的第一想法:使用双指针直接交换首尾元素,而后两指针分别向右和向左移动。

代码实现:

  • 我的思路
    public void reverseString(char[] s) {
        int length = s.length;
        int left = 0;
        int right = length - 1;
        //char ch;
        while (left < right) {
            //交换left,right元素
            //调用reverse函数没有改变顺序,应该是函数没有返回的问题?-->>
            //原因应当是你传入的知识字符,并不知道是数组,就是未将反转的元素与数组相关联
            //需要将数组也传进去才行,然后跟着一起变化
            reverse(s, left, right);
            /*ch = s[left];
            s[left] = s[right];
            s[right] = ch;*/
            left++;
            right--;
        }
    }
    public void reverse(char[] s, int i, int j) {
        char ch = s[i];
        s[i] = s[j];
        s[j] = ch;
    }

实现过程中遇到哪些困难

  • 交换的时候仅仅将元素传了进去,未传入字符数组,所有交换失败,应将字符数组也同步传进去。

541  反转字符串II

题目链接

代码随想录day08| 344.反转字符串、541. 反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串_第2张图片

看到题目的第一想法:我的思路是,字符串长度len分别对2k做求余数和求商的操作,然后分别处理前2ki中以2k为步进值得前k部分,而后对余数判断与k的大小关系,而后分别进行处理,但是处理的很混乱,导致无法ac,后续再看看。

  • 当需要固定规律一段一段去处理字符串的时候,要想想在for循环的表达式上做做文章,写出来的代码会更加高效

我的代码

    public String reverseStr(String s, int k) {
        int length = s.length();
        if (length < k) {
            return s;
        }
        int yushu = length % (2 * k);
        int times = length / (2 * k);
        String str = "";
        for (int i = 0; i < times; i++) {
            //substring而非subString
            String si = s.substring(2 * k * i, (2 * i + 1) * k);
            str += reverse(si, k);
            str += s.substring((2 * i + 1) * k, (2 * i + 2) * k);
        }
        if ( yushu > 0 && yushu < k) {
            str += reverse(s.substring(yushu), yushu);
        }else if (yushu >= k && yushu < 2 * k) {
            str += reverse(s.substring(length - yushu, length - yushu + k), k);
            str += s.substring(length - yushu + k);
        }
        return str;
    }
    //按照指定长度反转字符串
    public String reverse(String str, int l) {
        //l >= 1
        char[] ch = str.toCharArray();
        int len = ch.length;
        if (l > len) {
            l = len;
        }        
        int left = 0;
        int right  = l - 1;
        while (left < right) {
            char temp = ch[left];
            ch[left] = ch[right];
            ch[right] = temp;
            left++;
            right--;
        }
        return new String(ch);
    }

看完代码随想录之后的想法:卡哥给出的思路和代码就很清晰,每隔2k个元素反转前k个,若不够则全部反转

卡哥的代码实现:

public String reverseStr(String s, int k) {
        //自己的思路:2nk内的部分,每次反转前k个,而后判断剩余的元素与k的关系,代码比较复杂,也未能ac
        //卡哥的思路:每隔2k个元素反转前k个,若不够则全部反转
        char[] ch = s.toCharArray();
        int length = ch.length;
        for (int i = 0; i < length; i += 2 * k) {
            int start = i;
            //根据尾数够不够k个来判断end的位置
            int end = Math.min(length - 1, start + k - 1);
            while (start < end) {
                ch[start] ^= ch[end];
                ch[end] ^= ch[start];
                ch[start] ^= ch[end];
                start++;
                end--;
            }
        }
        return new String(ch);
    }
    }

实现过程中遇到哪些困难:

  • 有思路,实现还是有点问题,并且自己的思路比较复杂。
  • 卡哥代码中尾数判断很巧妙。字符串比较长时,前几次循环必定有start+k+1代码如下:
for (int i = 0; i < length; i += 2 * k) {
            int start = i;
            //根据尾数够不够k个来判断end的位置
            int end = Math.min(length - 1, start + k - 1);

剑指Offer 05  替换空格

题目链接

代码随想录day08| 344.反转字符串、541. 反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串_第3张图片

看到题目的第一想法:因为这道题之前做过,看到题之后知道要对字符串进行加长,但StringBuilder的使用不熟练,创建,设置值等。

看完代码随想录之后的想法:双指针法也很实用,实现时比单纯使用StringBuilder更加复杂,在对字符串进行扩容的时候,需要注意的是,字符串应当在尾部扩容,而并非在遇到空格直接扩容(加空格)

代码实现:

public String replaceSpace(String s) {
        /*//使用stringbuilder更简单
        int len = s.length();
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < s.length(); i++) {
            if(' ' == s.charAt(i)) {
                sb.append("%20");
            } else {
                sb.append(s.charAt(i));
            }
        }
        return sb.toString();*/
        //另外一种方法是双指针
        int len = s.length();
        StringBuilder sb = new StringBuilder();
        sb.append(s);
        //应当先在字符串的最后扩容,不能遇到空格就扩容,因为前len个字符不可变化
        for(int i = 0; i < len; i++) {
            if(' ' == s.charAt(i)) {
                //此处需要注意
                sb.append("  ");
            }
        }
        if(sb.length() == len) {
            return s;
        }
        String str = sb.toString();
        char[] ch = str.toCharArray();
        int left = len - 1;
        int right = ch.length - 1;
        while (left >= 0) {
            if (ch[left] == ' ') {
                ch[right--] = '0';
                ch[right--] = '2';
                ch[right--] = '%';
                //ch[right] = '%';
            }else {
                ch[right--] = ch[left];
                //ch[right] = ch[left];
            }
            left--;
            //right--;
        }
        return new String(ch);
    }

实现过程中遇到哪些困难:

  • 需要熟悉stringbuilder的使用

151  翻转字符串里的单词

代码随想录day08| 344.反转字符串、541. 反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串_第4张图片

题目链接

看到题目的第一想法:看到题目的时候有思路,但是实现不了,需要加强练习,还有就是方法何时有返回值,何时用void还不太清楚。

看完代码随想录之后的想法:卡哥的代码很清晰,自己在消除中间多余空格时不会处理;sb的setCharAt()未使用过。

代码实现:

public String reverseWords(String s) {
        //太费劲了,比着写都有很多错的,什么时候方法用void,什么时候有返回值都需要注意
        //去除首尾的空格,去除中间连续的多个空格
        //完全反转字符串
        //反转每个单词
        StringBuilder sb = removeSpace(s);
        reverseWholeString(sb, 0, sb.length() - 1);
        reverseEachWord(sb);
        return sb.toString();
    }
    public StringBuilder removeSpace(String s){
        int left = 0;
        int right = s.length() - 1;
        //去除首尾的空格
        while (left <= right && s.charAt(left) == ' ') {
            left++;
        }
        while (right >= left && s.charAt(right) == ' ') {
            right--;
        }
        //去除中间的空格
        StringBuilder sb = new StringBuilder();
        while(left <= right) {
            char c = s.charAt(left);
            if(c != ' ' || sb.charAt(sb.length() - 1) != ' ') {
                sb.append(c);
            }
            left++;
        }
        return sb;
    }
    public void reverseWholeString(StringBuilder sb, int left, int right) {
        while (left < right) {
            char temp = sb.charAt(left);
            sb.setCharAt(left, sb.charAt(right));
            sb.setCharAt(right, temp);
            left++;
            right--;
        }
        //此方法是否有返回值
        /*char[] ch = s.toCharArray();
        int length = ch.length;
        //int left = 0;
        //int right = length - 1;
        while (left < right) {
            char temp = ch[left];
            ch[left] = ch[right];
            ch[right] = temp;
            left++;
            right--;
        }
        s = new String(ch);*/
    }

    public void reverseEachWord(StringBuilder s) {
        //char[] ch = s.toCharArray();
        //后面一个字符为空格时,反转前方单词
        int left = 0;
        int right = 1;
        int length = s.length();
        while(left < length){
            while (right < length && s.charAt(right) != ' '){
                right++;
            }
            reverseWholeString(s, left, right - 1);
            left = right + 1;
            right = left + 1;
        }
    }

实现过程中遇到哪些困难:

  • 边界处理上不利索
  • stringbuilder的使用不熟练
  • 不清楚如何去除字符串中间多余的空格,连续空格数量大于1时变为1,“sb.charAt(sb.length() - 1) != ' '”可以添加一个空格,而后面的空格就添加补上了,
while(left <= right) {
    char c = s.charAt(left);
    if(c != ' ' || sb.charAt(sb.length() - 1) != ' ') {
        sb.append(c);
    }
    left++;

剑指Offer58-II  左旋转字符串

代码随想录day08| 344.反转字符串、541. 反转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串_第5张图片

题目链接

看到题目的第一想法:看到题目后有思路,先完全反转,而后反转后n个,然后反转前len-n个。

看完代码随想录之后的想法:卡哥的方法中,方法没有返回值的时候一般使用stringbuilder,可以原地操作字符串;当然也可以有返回值string,稍微麻烦一点。

代码实现:

我的思路:有返回值

    public String reverseLeftWords(String s, int n) {
        //将元素反转,而后后面n个元素反转,前面s.length()-n个元素也反转
        s = reverseString(s, 0, s.length() - 1);
        s = reverseString(s, 0, s.length() - n - 1);
        s = reverseString(s, s.length() - n, s.length() - 1);
        return s;
    }
    public String reverseString(String s, int left, int right) {
        char[] ch = s.toCharArray();
        while(left < right) {
            char temp = ch[left];
            ch[left] = ch[right];
            ch[right] = temp;
            left++;
            right--;
        }
        return new String(ch);
    }

卡哥的方法:无返回值

    public String reverseLeftWords(String s, int n) {
        //将元素反转,而后后面n个元素反转,前面s.length()-n个元素也反转
        //使用StringBuilder()后面函数的返回值可以为void
        //sb操作其中的部分值时比较方便
        StringBuilder sb = new StringBuilder(s);
        reverseString(sb, 0, sb.length() - 1);
        reverseString(sb, 0, sb.length() - n - 1);
        reverseString(sb, sb.length() - n, sb.length() - 1);
        return sb.toString();
    }
    public void reverseString(StringBuilder s, int left, int right) {
        //char[] ch = s.toCharArray();
        while(left < right) {
            char temp = s.charAt(left);
            s.setCharAt(left, s.charAt(right));
            s.setCharAt(right, temp);
            left++;
            right--;
        }
    }

实现过程中遇到哪些困难:

  • 多熟悉stringbuilder的使用,多使用无返回值的方法

今日收获,记录一下自己的学习时长

  • 算法处理约4h,博客编写约1.5h
  • 熟悉了string与stringbuilder的使用,熟悉了相关算法,熟悉了无返回值方法的处理,有机会多复习!
  • 贵在坚持,加油!

你可能感兴趣的:(代码随想录算法学习,leetcode,算法,数据结构)