
本文详解java中通过双指针法反转字符串中各单词顺序的实现原理,重点剖析原始代码中因边界处理不当导致的空格错位问题,并提供可直接运行的修复版本及关键注意事项。
本文详解java中通过双指针法反转字符串中各单词顺序的实现原理,重点剖析原始代码中因边界处理不当导致的空格错位问题,并提供可直接运行的修复版本及关键注意事项。
在字符串处理中,“单词级反转”(如将 "I like ice cream!" 变为 "cream! ice like I")不同于简单字符倒序("!maerc eci ekil I"),它要求保持每个单词内部字符顺序不变,仅调整单词间的排列顺序。这需分两步完成:
- 逐个反转各单词内部字符;
- 整体反转整个字符数组。
原始代码采用 reverse(char[] str, int start, int end) 实现局部翻转,逻辑清晰,但关键缺陷在于 reverseWords 方法中调用 reverse(s, start, end) 时未跳过空格——当 s[end] == ' ' 为真时,end 指向空格本身,而 reverse 函数会将 start 到 end(含空格)全部参与交换,导致空格被错误地移入单词内部。
例如输入 "I like"(索引:0:'I', 1:' ', 2:'l', 3:'i', 4:'k', 5:'e'):
- 首次遇到空格在 end = 1,调用 reverse(s, 0, 1) → 交换 s[0] 和 s[1],结果变为 " Ilike"(开头多空格,'I' 被挤到位置1);
- 后续逻辑彻底失效。
✅ 正确做法是:在识别到空格时,只反转 start 到 end−1 的范围(即当前单词的末尾字符)。修复后的 reverseWords 方法如下:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
static char[] reverseWords(char[] s) {
int start = 0;
for (int end = 0; end < s.length; end++) {
if (s[end] == ' ') {
reverse(s, start, end - 1); // 关键修正:end → end-1
start = end + 1;
}
}
reverse(s, start, s.length - 1); // 反转最后一个单词(无后续空格)
reverse(s, 0, s.length - 1); // 整体反转,完成单词顺序调换
return s;
}? 补充说明:reverse 方法中 while(start <= end) 是安全的,因为当 start == end 时仅做一次“自交换”,不影响结果;而 start > end 时循环自然终止。所有变量(如 start、end)均为方法参数或局部变量,不同方法间的同名变量完全独立,互不干扰——这是理解递归/嵌套调用行为的基础。
完整可运行代码(已修复):
import java.util.*;
public class StringProblems {
static void reverse(char str[], int start, int end) {
while (start <= end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
}
static char[] reverseWords(char[] s) {
int start = 0;
for (int end = 0; end < s.length; end++) {
if (s[end] == ' ') {
reverse(s, start, end - 1);
start = end + 1;
}
}
reverse(s, start, s.length - 1);
reverse(s, 0, s.length - 1);
return s;
}
public static void main(String[] args) {
System.out.println("enter the string to be reversed");
Scanner ss = new Scanner(System.in);
String input = ss.nextLine();
char[] result = reverseWords(input.toCharArray());
System.out.println(result); // 输出:cream! ice like I
}
}? 注意事项:
- 输入含首尾空格或连续空格时,本实现会将其视作单词分隔符,但不会额外保留多余空格(因 nextLine() 读取整行,空格参与反转);若需鲁棒性处理,建议先 trim() 并按 "\s+" 分割再重组;
- 字符数组操作直接修改原引用内容,无需返回新数组(但为语义清晰仍返回);
- 时间复杂度 O(n),空间复杂度 O(1)(不计输入存储),符合原地算法要求。
掌握此模式,即可高效解决 LeetCode #151「翻转字符串里的单词」等经典题目。

















