代码随想录第九天|151.翻转字符串里的单词、卡码网:55.右旋转字符串、28. 实现 strStr() 、459.重复的子字符串
题目:151. 翻转字符串里的单词
给定一个字符串 s
,逐个翻转字符串中的每个单词。
示例 1:
- 输入:
"the sky is blue"
- 输出:
"blue is sky the"
要求:
- 请确保每个单词之间只有一个空格。
- 删除开头和结尾的所有空格。
解题思路
-
去除多余空格
- 首先,删除字符串开头和结尾的空格,并将中间多余的空格压缩成一个空格。使用
removeSpaces
方法实现这个功能。
- 首先,删除字符串开头和结尾的空格,并将中间多余的空格压缩成一个空格。使用
-
翻转整个字符串
- 将处理过的字符串整体翻转,这样每个单词的位置就变成了逆序。使用两个指针(
left
和right
)从字符串的两端向中间移动并交换字符。
- 将处理过的字符串整体翻转,这样每个单词的位置就变成了逆序。使用两个指针(
-
逐个翻转单词
- 在逆序的基础上,通过遍历每个单词,再次将每个单词单独翻转回来,这样就可以得到正确的顺序。用两个指针分别记录每个单词的起始和结束位置,然后对其进行翻转。
反思
在编写这段代码的过程中,主要出现了以下几个错误点,可以通过反思来总结编程中的常见问题和改进方向:
-
拼写错误和拼写检查的重要性
- 问题:在代码中多次出现拼写错误,如
toChat
和toChar
。这些错误会导致程序编译失败,并难以排查。 - 反思:拼写错误是非常容易避免的,可以通过使用 IDE(集成开发环境)中的自动补全和代码检查功能来减少此类错误。此外,编写代码时应注意细心核对每个函数和变量的拼写。
- 问题:在代码中多次出现拼写错误,如
-
类型错误和字符比较问题
- 问题:错误地使用
==
比较字符串而不是字符,导致程序逻辑无法正确执行。例如,将s.toChat(start) != " "
改成了字符比较s.charAt(start) != ' '
。 - 反思:Java 中,
==
比较的是引用,而不是内容。在比较字符串内容时,需要使用equals
方法;而比较字符时,需要使用单引号''
。理解并区分字符与字符串的操作方法,有助于减少逻辑错误。
- 问题:错误地使用
-
未定义变量和变量声明错误
- 问题:在
removeSpaces
方法中使用了未定义的变量c
,导致代码无法编译。 - 反思:在编写代码时,应确保所有变量都已正确声明并初始化。尤其是在重构代码时,确保修改后的代码中没有遗漏变量的定义。
- 问题:在
-
数据类型转换问题
- 问题:代码尝试直接使用
char[]
数组的toString()
方法来返回字符串,但这会返回对象的默认字符串表示而不是字符数组的内容。 - 反思:在使用数据结构时,需要理解它们的工作方式和相关方法。在处理数组时,直接使用
new String(charArray)
来转换为字符串是一种更好的方法。
- 问题:代码尝试直接使用
-
逻辑错误和逻辑的复用
- 问题:翻转单词的逻辑没有正确重置
left
和right
,导致字符串不能正确反转。代码结构中存在冗余部分,使逻辑不够清晰。 - 反思:在编写复杂逻辑时,建议将代码块分解为单一功能的辅助方法。这不仅提高代码的可读性,还方便复用。通过编写清晰的逻辑并拆分成多个函数,可以减少逻辑上的错误。
- 问题:翻转单词的逻辑没有正确重置
-
有效利用辅助工具
- 问题:在调试过程中,若缺乏良好的代码检查工具,容易出现拼写和逻辑错误。
- 反思:利用 IDE 提供的静态分析、错误提示和重构功能,可以有效减少编程过程中的人为错误。在调试和重构代码时,可以通过单元测试和自动化测试来捕捉逻辑缺陷。
总结:这次的错误主要集中在拼写、类型比较、未定义变量、数据类型转换和逻辑实现方面。解决这些问题的关键在于:细心、谨慎,合理利用工具,提高代码模块化和可读性。编程是一门细致的工作,写代码时应不断养成良好的习惯,减少不必要的错误。
代码
class Solution {
public StringBuilder removeSpaces(String s) {
int start = 0;
int end = s.length() - 1;
// 去除开头的空格
while (start <= end && s.charAt(start) == ' ') {
start++;
}
// 去除结尾的空格
while (end >= start && s.charAt(end) == ' ') {
end--;
}
StringBuilder sb = new StringBuilder();
while (start <= end) {
char c = s.charAt(start);
// 仅在当前字符不为空格或 sb 中的最后一个字符不是空格时添加
if (c != ' ' || (sb.length() > 0 && sb.charAt(sb.length() - 1) != ' ')) {
sb.append(c);
}
start++;
}
return sb;
}
public String reverseWords(String s) {
StringBuilder sb = removeSpaces(s);
int left = 0;
int right = sb.length() - 1;
// 翻转整个字符串
reverse(sb, left, right);
int start = 0;
for (int i = 0; i <= sb.length(); i++) {
if (i == sb.length() || sb.charAt(i) == ' ') {
// 翻转每个单词
reverse(sb, start, i - 1);
start = i + 1;
}
}
return sb.toString();
}
// 辅助方法,用于翻转字符串中的字符
private void reverse(StringBuilder sb, int left, int right) {
while (left < right) {
char temp = sb.charAt(left);
sb.setCharAt(left, sb.charAt(right));
sb.setCharAt(right, temp);
left++;
right--;
}
}
}
题目:字符串右旋转
字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s
和一个正整数 k
,请编写一个函数,将字符串中的后面 k
个字符移到字符串的前面,实现字符串的右旋转操作。
示例:
- 输入:
"abcdefg"
和整数2
- 输出:
"fgabcde"
解题思路:
- 将整个字符串进行翻转;
- 翻转前
k
个字符; - 翻转后
n-k
个字符。
反思
这道题通过分步骤翻转字符串实现右旋转操作,展现了使用双指针和异或操作的巧妙性。通过三步翻转实现了高效的字符串旋转,可以有效避免多次移动字符带来的时间复杂度增加。
代码
// 版本一
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);
reverseString(chars,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];
end--;
start++;
}
}
}