代码随想录算法训练营Day9|翻转字符串里的单词、右旋转字符串、实现 strStr()、重复的子字符串

151.翻转字符串里的单词

这题以前也做过,祝我好运。要用StringBuilder,还有去除左右两侧空格的方法
我先把没编译过的代码po上来,给自己加深一下记忆。(最好加深的是正确的记忆)

class Solution {
    public String reverseWords(String s) {
        // 去除两侧空格
        s.trim();
        // 
        StringBuilder ans = new StringBuilder();
        // 指针,从后往前扫描源字符串,然后从前往后加入ans
        int j = s.length() - 1, i = j;
        while(j >= 0) {
            // 用i限定一个单词的左侧,j限定右侧
            while(i > 0 && s.charAt(i) != ' ') i--;
            ans.append(s.subString(i + 1, j + 1));
            while(i > 0 && s.charAt(i) == ' ') i--;
            j = i;
        }
        return ans.toString();
    }
}
Line 12: error: cannot find symbol
            ans.append(s.subString(i + 1, j + 1));

第一个报错。substring()才是正确的!
第二个问题String类型的修改,s = s.trim()才是正确的
还有逻辑问题,边界选的不对。这里的循环都是基于i做判定的,而不是j。所以大循环的判断也应该是和i挂钩的。
最后所有字符串末尾还有一个空格,需要用s.trim()删掉
这是修改后的代码。

class Solution {
    public String reverseWords(String s) {
        // 去除两侧空格
        s = s.trim();
        // 
        StringBuilder ans = new StringBuilder();
        // 指针,从后往前扫描源字符串,然后从前往后加入ans
        int j = s.length() - 1, i = j;
        while(i >= 0) {
            // 用i限定一个单词的左侧,j限定右侧
            while(i >= 0 && s.charAt(i) != ' ') i--;
            ans.append(s.substring(i + 1, j + 1)).append(' ');
            while(i >= 0 && s.charAt(i) == ' ') i--;
            j = i;
        }
        // 删除最后一个多余的空格
        return ans.toString().trim();
    }
}

右旋转字符串

这题第一反应是多次反转,第一次,反转整个字符串,第二次反转前面n个字符串,第三次反转最后length-n个字符串。
这里有一个之前反转字符串时遗留的算法。异或法反转字符串

class Solution {
    public void reverseString(char[] s) {
        int n = s.length;
        int left = 0, right = n - 1;
        while(left < right) {
            // 用异或法交换字符
            s[left] ^= s[right];
            s[right] ^= s[left];
            s[left] ^= s[right];

            left++;
            right--;
        }
    }
}

假设 a 和 b 的初始值分别为 A 和 B,交换过程如下:

第一步:a = a ^ b;

现在 a 的值变为 A ^ B,而 b 仍然是 B。
现在:a = A ^ B,b = B
第二步:b = a ^ b;

现在 b 的值变为 (A ^ B) ^ B。
根据异或的结合律和性质 (A ^ B) ^ B = A,所以 b 的值变成了 A。
现在:a = A ^ B,b = A
第三步:a = a ^ b;

现在 a 的值变为 (A ^ B) ^ A。
根据异或的结合律和性质 (A ^ B) ^ A = B,所以 a 的值变成了 B。
现在:a = B,b = A
此时,a 和 b 的值已经完成交换。
可以对该代码稍加改造,变成一个可以指定边界的方法

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = Integer.parseInt(in.nextLine());
        String s = in.nextLine();

        int len = s.length();  //获取字符串长度
        char[] chars = s.toCharArray();
        reverseString(chars, 0, len - 1);  //反转整个字符串
        reverseString(chars, 0, n - 1);  //反转前一段字符串,此时的字符串首尾尾是0,n - 1
        reverseString(chars, n, len - 1);  //反转后一段字符串,此时的字符串首尾尾是n,len - 1
        
        System.out.println(chars);

    }

    public static void reverseString(char[] ch, int start, int end) {
        //异或法反转字符串,参照题目 344.反转字符串的解释
        while (start < end) {
            ch[start] ^= ch[end];
            ch[end] ^= ch[start];
            ch[start] ^= ch[end];
            start++;
            end--;
        }
    }
}

28. 实现 strStr()

这题就是经典的KMP算法,我真的刷了几次了。之前也是自己能完整敲出来,可能也就是大半个月之前。现在又全忘了。。。。逆天
我还有印象,KMP算法最难的是构建next数组。我试试。
唉,鱼的记忆。今天还是先把StringBuilder、String、Scanner学了。后面先跳过去。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值