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学了。后面先跳过去。