力扣刷题第一天|344.反转字符串、541. 反转字符串 II、剑指 Offer 05. 替换空格、151. 反转字符串中的单词、剑指 Offer 58 - II. 左旋转字符串

力扣刷题第一天|344.反转字符串、541. 反转字符串 II、剑指 Offer 05. 替换空格、151. 反转字符串中的单词、剑指 Offer 58 - II. 左旋转字符串

344. 反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(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
给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

  • 如果剩余字符少于 k 个,则将剩余字符全部反转。
  • 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

第一次解答这道题目的思路比较复杂,写了一堆逻辑代码,还加了一个计数器,来统计2k,再统计前k个字符,最后虽然能通过测试,但代码不简洁。
代码:

public String reverseStr1(String s, int k) {
        int count = 0, stratIndex, endIndex;
        char[] arr = s.toCharArray();
        for (int i = 0; i < arr.length; i++) {
            count++;
            if(arr.length < k){
                stratIndex = 0;
                endIndex = arr.length - 1;
                for (int x = stratIndex, y = endIndex;x < y;x++,y--) {
                    char temp = arr[x];
                    arr[x] = arr[y];
                    arr[y] = temp;
                }
                return new String(arr);
            } else if (arr.length >= k && arr.length < 2 * k) {
                stratIndex = 0;
                endIndex = k - 1;
                for (int x = stratIndex, y = endIndex;x < y;x++,y--) {
                    char temp = arr[x];
                    arr[x] = arr[y];
                    arr[y] = temp;
                }
                return new String(arr);
            }
            if (count == 2 * k) {
                stratIndex = i + 1 - 2 * k;
                endIndex = i - k;
                for (int x = stratIndex, y = endIndex;x < y;x++,y--) {
                    char temp = arr[x];
                    arr[x] = arr[y];
                    arr[y] = temp;
                }
                if ((s.length() - 1 - i) < k) {
                    if((s.length() - 1 - i) == 0){
                        return new String(arr);
                    }
                    stratIndex = i + 1;
                    for (int x = stratIndex, y = arr.length - 1;x < y;x++,y--) {
                        char temp = arr[x];
                        arr[x] = arr[y];
                        arr[y] = temp;
                    }
                    return new String(arr);
                } else if ((s.length() - 1 - i) >= k && (s.length() - 1 - i) < 2 * k) {
                    stratIndex = i + 1;
                    endIndex = i + k;
                    for (int x = stratIndex, y = endIndex; x < y;x++,y--) {
                        char temp = arr[x];
                        arr[x] = arr[y];
                        arr[y] = temp;
                    }
                    return new String(arr);
                } else {
                    stratIndex = i + 1;
                    count = 0;
                }
            }
        }
        return new String(arr);
    }

第二次借鉴了别人的代码后发现只要在遍历字符串的过程中,让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。

结论:当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。
代码:

class Solution {
    public String reverseStr(String s, int k){
        char[] arr = s.toCharArray();
        for (int i = 0; i < arr.length; i += 2 * k) {
            reverse(arr,i,Math.min(i + k - 1,arr.length - 1));
        }
        return new String(arr);
    }
    public void reverse(char[] arr,int stratIndex,int endIndex){
        for (int x = stratIndex,y=endIndex; x < y; x++,y--) {
            char temp = arr[x];
            arr[x] = arr[y];
            arr[y] = temp;
        }
    }
}

剑指 Offer 05. 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

刚开始拿到题目时,直接调用了Java的库函数,一行代码解决问题,但这样做对于理解字符串的替换过程没有多少帮助,后来采用了官方的解题思路,创建一个新的字符数组解决问题。
代码:

public String replaceSpace(String s) {
        char[] arr = new char[s.length() * 3];
        int index = 0;
        for (int i = 0; i < s.length(); i++) {
            if(s.charAt(i) == ' '){
                arr[index++] = '%';
                arr[index++] = '2';
                arr[index++] = '0';
            }else{
               arr[index++] = s.charAt(i);
           }
        }
       return new String(arr,0,index);
    }

在官方给出的解题思路上继续做出改进,将字符数组换为StringBuilder字符串,可以将占用的内存变得更少。
代码:

class Solution {
  public String replaceSpace(String s) {
        int count = 0;
        StringBuilder builder = new StringBuilder(s.length() * 3);
        for (int i = 0; i < s.length(); i++) {
            count++;
            if(s.charAt(i) == ' '){
                builder.append("%20");
                count = 0;
            }else{
                builder.append(s.charAt(i));
            }
        }
        return builder.toString();
    }
}

151. 反转字符串中的单词
给你一个字符串 s ,请你反转字符串中单词的顺序。

单词是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的单词分隔开。

返回单词顺序颠倒且单词之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

这道题我直接使用了Java中自带的库函数来解决问题:

  1. 使用 trim() 将字符串首尾空格去掉;
  2. 使用 split 将字符串按空格分割成字符串数组;
  3. 定义一个StringBuilder变量并调用for循环将字符串数组拼接成一个满足要求的字符串。

代码:

class Solution {
    public String reverseWords(String s) {
        String str = s.trim();
        String[] arrStr = str.split("\\s+");
        StringBuilder builder = new StringBuilder(arrStr.length);
        for (int i = arrStr.length - 1; i >= 0; i--) {
            builder.append(arrStr[i]);
            if(i != 0){
                builder.append(" ");
            }
        }
        return builder.toString();
    }
}

剑指 Offer 58 - II. 左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

这道题目通过使用String自带的substring()函数将原字符串切片,再利用StringBuilder的append()函数将两个字串连接起来。
代码:

class Solution {
    public String reverseLeftWords(String s, int n) {
        StringBuilder builder = new StringBuilder(s.length());
        builder.append(s.substring(n));
        builder.append(s.substring(0,n));
        return builder.toString();
    }
}

收获:通过这几道题目的练习,对Java中字符串常用函数的用法更加熟悉,对于for循环也有了进一步的了解,思维逻辑也得到了一定训练。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值