代码随想录第十二期集训营-第八天

今天学习代码随想录新的一章--字符串,完成以下题目

344.反转字符串

这题要求输入:["h","e","l","l","o"] 输出:["o","l","l","e","h"],而且题目中要求你不能再额外开辟空间,也就是不能再创建一个数组,用倒叙遍历原数组这种方式。我们只能对原数组进行操作,利用双指针法,一个在头一个在尾,交换就行。

541.反转字符串||

输入: s = "abcdefg", k = 2输出: "bacdfeg"

这题也是用双指针,关键就是要找明白哪个是start指针,哪个是end指针。题目要求从字符串开头算起, 每计数至 2k 个字符,就反转这 2k 个字符中的前 k 个字符。因此我们可以让for循环中的变量i为start,步长就是2*k,这次start是i,下次start就是i+2*k。end指针就是从i开始数k个数就行,就是end = i + k - 1(这时是从i所在元素开始的剩余元素数量大于k)。但是如果剩余元素不足k个时(也就是i +k-1 > s.length-1),end就是数组尾部索引,因此求end指针时要判断剩余元素和k的大小,取二者小值,之后交换就行。

class Solution {
    public String reverseStr(String s, int k) {
        //每次遍历字符串的步长 i += 2k
        char[] ch = s.toCharArray();
        for(int i = 0;i < ch.length;i += 2*k){
            //起始索引就在i处
            int start = i;
            //找终止索引
            //找的时候就就要判断剩下的元素够不够k个,比k大那end就正常指向start + k -1处,然后交换这k个元素。没有k大end就指向末尾,有几个就交换几个。
            int end = Math.min(ch.length - 1,start + k -1);
            //交换
            while(start < end){
                char temp = ch[start];
                ch[start] = ch[end];
                ch[end] = temp;
                start++;
                end--;
            }
        }

        return new String(ch);
    }
}

剑指Offer 05.替换空格

输入:s = "We are happy."输出:"We%20are%20happy."

这题做到极致,是不需要创建额外空间,对原字符串操作就行。先对原数组进行扩容,然后再用双指针填充即可

1.创建一个StringBuilder,名字就叫sb,用来做扩容的

2.遍历s,遇到一个空格,sb就执行append(" "),添加有两个空格的字符串,注意是两个,因为原来一个空格变成"%20",多了两个位置存放字符,那额外再加两个空格就有三个空格了,补充了%20的大小。就比如原来s = " We are",大小为6,扩容之后大小为8。

3.把sb转成字符串,再用字符串拼接完成s的扩容。s += sb.toString()

4.双指针法,一个指针left指向原s的尾部,例子中的y这个位置,另一个指针right指向扩容后数组尾部。然后把left对应的元素复制到right,遇到空格就要在right位置按顺序填写%20。

如果之后遇到填充数组的问题,都可以考虑先扩充数组,然后从后向前填充。如果从前向后填充,会让后面的元素都移动,这样时间复杂度就变成O(n²)了。

public String replaceSpace(String s) {
    if(s == null || s.length() == 0){
        return s;
    }
    //扩充空间,空格数量2倍
    StringBuilder str = new StringBuilder();
    for (int i = 0; i < s.length(); i++) {
        if(s.charAt(i) == ' '){
            str.append("  ");
        }
    }
    //若是没有空格直接返回
    if(str.length() == 0){
        return s;
    }
    //有空格情况 定义两个指针
    int left = s.length() - 1;//左指针:指向原始字符串最后一个位置
    s += str.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);
}

151.翻转字符串里的单词

输入: "the sky is blue"输出: "blue is sky the"

输入: "  hello world!  "输出: "world! hello"

这题有点麻烦,分为三步,对应三个方法。

1.去除字符串多余空格

2.反转整个字符串

3.反转字符串里的每个单词

讲一下去除空格的细节,对一个字符串,先去除头部空格,再去除尾部空格,最后去除中间多余空格。用双指针法,头部指针用来去除头部空格,尾部指针去除尾部空格,最后遍历中间的,去除空格。

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);
            if (c != ' ' || sb.charAt(sb.length() - 1) != ' ') {
                sb.append(c);
            }
            start++;
        }
        // System.out.println("ReverseWords.removeSpace returned: sb = [" + sb + "]");
        return sb;
    }
class Solution {
    public String reverseWords(String s) {
        //一共三个步骤
        //1.去除多余空格
        //2.反转整个s
        //3.反转每个单词
        String str = removeSpace(s);
        str = reverseString(str,0,str.length()-1);
        str = reverseWord(str);
        return str;

    }

    public  String reverseWord(String s){
        int start = 0;
        int end = 1;
        while(start < s.length()){
            while(end < s.length() && s.charAt(end) != ' '){
                end++;
            }
            s = reverseString(s,start,end-1);
            start = end+1;
            end = end+1;
        }


        return s;
    }
    public  String reverseString(String s,int start,int end){

        char[] ch = s.toCharArray();

        while(start < end){
            char temp = ch[start];
            ch[start] = ch[end];
            ch[end] = temp;
            start++;
            end--;
        }

        return new String(ch);
    }
    public  String 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){
            if(s.charAt(start) != ' ' || sb.charAt(sb.length() - 1) != ' ' ){
                sb.append(s.charAt(start));
            }
            start++;
        }

        return new String(sb);
    }

}

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

输入: s = "abcdefg", k = 2输出: "cdefgab"

这题我的做法是用到了替换空格这题中的思路,先扩充k个单元,然后用双指针复制,不难。

class Solution {
    public String reverseLeftWords(String s, int n) {
         //先扩张
        StringBuilder sb = new StringBuilder();
        for(int i = 0;i < n;i++){
            sb.append(" ");
        }

        //双指针

        int right = s.length();
        s += sb.toString();
        char[] ch = s.toCharArray();

        for(int left = 0;left < n;left++){
            ch[right] = ch[left];
            right++;
        }

        StringBuilder newSb = new StringBuilder();
        for(int i = n;i < ch.length;i++){
            newSb.append(ch[i]);
        }
        return new String(newSb);
    }
}

代码随想录中的做法是先反转前k个元素,再反转后面的元素,最后反转整个字符串,大家可以试试。

#2022毕业即失业取暖地##2022毕业生求职现身说法##2022毕业的你对23届的寄语##如何判断面试是否凉了#
全部评论

相关推荐

30 3 评论
分享
牛客网
牛客企业服务