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

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

344.反转字符串

建议: 本题是字符串基础题目,就是考察 reverse 函数的实现,同时也明确一下 平时刷题什么时候用 库函数,什么时候 不用库函数

题目链接/文章讲解/视频讲解:
在这里插入图片描述

看到题目的第一想法:

双指针法:
设置两个指针,分别指向字符数组的开头和结尾,两两交换。

package com.second.day8;

public class ReverseString_344 {
    public void reverseString(char[] s) {
        int left = 0;
        int right = s.length - 1;
        while(left < right) {
            char c = s[left];
            s[left] = s[right];
            s[right] = c;
            left++;
            right--;
        }
    }
}

看完代码随想录之后的想法:

easy

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

easy

541. 反转字符串II

建议:本题又进阶了,自己先去独立做一做,然后在看题解,对代码技巧会有很深的体会。

题目链接/文章讲解/视频讲解:
在这里插入图片描述

看到题目的第一想法:

这道题,debug了半天最后才出来,有很多小细节处理的不到位。觉得这道题就是按照题目要求处理好遍历问题。

package com.second.day8;

public class ReverseStr_541 {
    public String reverseStr(String s, int k) {
        char[] str = s.toCharArray();
        //字符长度小于等于k直接翻转返回
        if(s.length() <= k) {
            reverse(str, 0, str.length - 1);
            return String.valueOf(str);
        }
        //count用来表示何时可以翻转
        int count = 0;
        for(int i = 0; i < str.length; i += k) {
            if(count % 2 == 0) {
                //当剩余字符小于等于k时,剩余部分进行翻转后返回
                if(str.length - i <= k) {
                    reverse(str, i, str.length - 1);
                    return String.valueOf(str);
                }
                //count为0或偶数时进行翻转
                reverse(str, i, i + k - 1);
            }
            count++;
        }
        return String.valueOf(str);
    }

    //翻转字符数组s序号为[left, right]的字符串
    public void reverse(char s[], int left, int right) {
        while (left < right) {
            char c = s[left];
            s[left] = s[right];
            s[right] = c;
            left++;
            right--;
        }
    }

    public static void main(String[] args) {
        ReverseStr_541 demo = new ReverseStr_541();
        demo.reverseStr("hyzqyljrnigxvdtneasepfahmtyhlohwxmkqcdf ehybknvdmfrfvtbsovjbdhevlfxpdaovjgunjql imjkfnqcqnajmebeddqsgl", 39);
    }
}

看完代码随想录之后的想法:

好吧,是我输麻了。
卡哥代码太简洁了。
用java实现一下。

//翻转字符数组s序号为[left, right]的字符串
    public void reverse(char s[], int left, int right) {
        while (left < right) {
            char c = s[left];
            s[left] = s[right];
            s[right] = c;
            left++;
            right--;
        }
    }

    public String reverseStr1(String s, int k) {
        char[] str = s.toCharArray();
        for(int i = 0; i < str.length; i += 2 * k) {
            // 1. 每隔 2k 个字符的前 k 个字符进行反转
            // 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
            if(i + k < str.length) {
                reverse(str, i, i + k - 1);
            }
            else {
                // 3. 剩余字符少于 k 个,则将剩余字符全部反转。
                reverse(str, i, str.length - 1);
            }
        }
        return String.valueOf(str);
    }

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

字符数组转为字符串
String.valueOf(ch)
new String(ch)

剑指Offer 05.替换空格

建议:对于线性数据结构,填充或者删除,后序处理会高效的多。好好体会一下。
题目链接/文章讲解:

在这里插入图片描述

看到题目的第一想法:

1.遍历字符串统计其中有多少个空格
2.设置一个大小匹配的的字符数组str
3.遇到空格就到str中加入“%20”,否则加原字符

package com.second.day8;

public class ReplaceSpace_jz05 {
    public String replaceSpace(String s) {
        //遍历s统计有多少个空格
        int count = 0;
        for(int i = 0; i < s.length(); i++) {
            if(s.charAt(i) == ' ')
                count++;
        }
        //设置一个大小匹配的的字符数组str
        char[] str = new char[s.length() + 2 * count];
        int index = 0;
        for(int i = 0; i < s.length(); i++) {
            if(s.charAt(i) == ' ') {
                str[index++] = '%';
                str[index++] = '2';
                str[index++] = '0';
            }
            else {
                str[index++] = s.charAt(i);
            }
        }
        return String.valueOf(str);
    }
}

看完代码随想录之后的想法:

自己写的代码和卡哥最好的方法是一致的。牛逼plus!

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

151.翻转字符串里的单词

建议:这道题目基本把 刚刚做过的字符串操作 都覆盖了,不过就算知道解题思路,本题代码并不容易写,要多练一练。

题目链接/文章讲解/视频讲解:
在这里插入图片描述

看到题目的第一想法:

从后往前推,记下每个单词的头和尾,然后添加入新的字符串中,只要不是首个单词,每个字符加个空格。

package com.second.day8;

public class ReverseWords_jz58 {
    public String reverseWords(String s) {
        //构造一个StringBuilder字符串构建器。
        StringBuilder sb = new StringBuilder();
        int left = s.length() - 1;
        //去除前导空格
        int start = 0;
        while(start < left && s.charAt(start) == ' ') {
            start++;
        }
        while(left >= start) {
            //遇到空格就前进一位
            while(left >= start && s.charAt(left) == ' ') {
                left--;
            }
            //此时遇到了字符的末尾,记下来
            int end = left;
            while(left >= start && s.charAt(left) != ' ') {
                left--;
            }
            //此时记入了字符的开头的第一个字符
            int begin = left + 1;
            //将该字符加入sb中
            while(begin <= end) {
                sb.append(s.charAt(begin));
                begin++;
            }
            //若不是第一个字符就在最后还加一个空格
            if(left + 1 != start)
                sb.append(' ');
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        ReverseWords_jz58 demo = new ReverseWords_jz58();
        demo.reverseWords("the sky is blue");
    }
}

看完代码随想录之后的想法:

方法也太多了吧!!!看看卡哥怎么实现的,一个个看,不要放弃哦!
解法一:

class Solution {
    public String reverseWords(String s) {
        StringBuilder sb = removeSpace(s);
        reverseString(sb, 0, sb.length() - 1);
        reverseWord(sb);
        return new String(sb);
    }

    //去除首尾以及中间多余空格
    public StringBuilder removeSpace(String s) {
        StringBuilder sb = new StringBuilder();
        int start = 0;
        int finish = s.length() - 1;
        //去除前导空格
        while(start < s.length() && s.charAt(start) == ' ')
            start++;
        //去除后导空格
        while(finish >= start && s.charAt(finish) == ' ')
            finish--;
        //去除中间字符的多余空格
        while(start <= finish) {
            char c = s.charAt(start);
            if(c == ' ' && s.charAt(start - 1) == ' ') {
                start++;
                continue;
            }
            sb.append(c);
            start++;
        }
        return sb;
    }

    //反转整个字符串
    public void reverseString(StringBuilder sb, int left, int right) {
        while(left < right) {
            char c = sb.charAt(left);
            sb.setCharAt(left, sb.charAt(right));
            sb.setCharAt(right, c);
            left++;
            right--;
        }
    }

    //反转各个单词
    public void reverseWord(StringBuilder sb) {
        int start = 0;
        while(start < sb.length()) {
            int begin = start;
            while(start < sb.length() && sb.charAt(start) != ' ')
                start++;
            if(start != sb.length() - 1)
                reverseString(sb, begin, start - 1);
            else
                reverseString(sb, begin, start);
            start++;
        }
    }
}

解法二:
和我自己想的差不多,俺真棒!
解法三,四和解法一二大同小异。

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

StringBuilder和StringBuffer用的不太熟练。

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

建议:题解中的解法如果没接触过的话,应该会想不到

题目链接/文章讲解:
在这里插入图片描述

看到题目的第一想法:

1.构造一个StringBuilder字符串构建器sb。
2.将字符串s的[n,s.length-1]添加到sb中
3.将字符串s[0,n - 1]添加到sb中

package com.second.day8;

public class ReverseLeftWords_jz58_2 {
    public String reverseLeftWords(String s, int n) {
        //构造一个StringBuilder字符串构建器sb。
        StringBuilder sb = new StringBuilder();
        //将字符串s的[n,s.length-1]添加到sb中
        for(int i = n; i < s.length(); i++) {
            sb.append(s.charAt(i));
        }
        //将字符串s[0,n - 1]添加到sb中
        for(int i = 0; i < n; i++) {
            sb.append(s.charAt(i));
        }
        return sb.toString();
    }
}

看完代码随想录之后的想法:

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

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

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

今天的题目难度对我来说还是比较适中的,都能够很快想到思路,然后AC出。加油,少年,坚持下去。
今天写了五个题:
344.反转字符串 , 541. 反转字符串II, 剑指Offer 05.替换空格 ,151.翻转字符串里的单词,剑指Offer58-II.左旋转字符串
代码:1.5h
博客:1.5h
努力是一种生活态度,与年龄无关。所以,无论什么时候,千万不可放纵自己,给自己找懒散和拖延的借口,对自己严格一点儿,时间长了,努力便成为一种心理习惯,一种生活方式!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是nefu小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值