本文详解如何正确统计字符串中“相邻重复数字组”的数量(如 "1 1 2 7 7 7 7 3 3 5 3" 中的 "1 1"、"7 7 7 7"、"3 3" 共 3 组),纠正初学者常见的边界越界与逻辑误判问题。
本文详解如何正确统计字符串中“相邻重复数字组”的数量(如 "1 1 2 7 7 7 7 3 3 5 3" 中的 "1 1"、"7 7 7 7"、"3 3" 共 3 组),纠正初学者常见的边界越界与逻辑误判问题。
在解决 adjacentDuplicatesCount 问题时,核心目标是:
统计“连续相同数字构成的块”的数量,而非统计所有相邻相等的字符对
。例如输入 "1 1 2 7 7 7 7 3 3 5 3"(含空格),应识别出三组相邻重复:"1 1"(1组)、"7 7 7 7"(1组)、"3 3"(1组)→ 总计
3 组
。
你原始代码的问题在于:
使用 Scanner 拼接为无空格字符串(如 "11277773353"),导致 '1','1' → '1','2' → '2','7' …… 这样会把 "7777" 错误拆解为
3 对相邻相等
(即索引 3=4、4=5、5=6),再加上 "11" 和 "33" 各 1 对,共 5 对;而你的循环范围 i < result.length() - 1 实际遍历了 i=1 到 i=length-2,又漏掉首对,最终凑出 4 —— 这正是“多算 1”的根源。
✅ 正确思路是:
逐个读取 token(数字),比较当前 token 与前一个 token 是否相同;若相同且前一个已形成重复,则仅在“重复开始处”计数 1 次
。
以下是推荐的简洁、健壮实现:
⚠️ 注意事项:
必须调用 reader.close()
防止资源泄漏;
使用 reader.peek()(需 Java 19+)可预览下一个 token 而不消耗它;若使用低版本 JDK,请改用临时变量缓存:
不要拼接字符串后遍历字符 —— 空格语义丢失,数字位数混淆(如 "11" 和 "1 1" 在拼接后无法区分);
Map 方案(答案中提供)实际统计的是「出现次数 ≥2 的数字种类数」,例如 "7 7 7 7" 和 "7 7" 都只算 1 次,但它
无法区分是否相邻
("7 1 7" 也会被误计),因此不符合题意中“Adjacent Duplicates”的严格定义。
? 总结:相邻重复组计数 = 一次遍历 + 状态记忆(prev)+ 贪心跳过(连续相同则跳过后续)。这既是算法思维训练,也是 Scanner 实际应用的典型范式。
public static int adjacentDuplicatesCount(String str) {
Scanner reader = new Scanner(str);
int count = 0;
String prev = null;
while (reader.hasNext()) {
String curr = reader.next();
// 当前数字等于前一个,且之前尚未计入该组 → 计数+1
if (prev != null && curr.equals(prev)) {
count++;
// 关键:跳过后续连续相同的项(如7777只计1次)
while (reader.hasNext() && reader.peek().equals(curr)) {
reader.next(); // 消耗掉后续重复项
}
}
prev = curr;
}
reader.close();
return count;
}String next = null;
while (reader.hasNext()) {
String curr = next != null ? next : reader.next();
next = reader.hasNext() ? reader.next() : null;
// ... 逻辑同上,用 next 替代 peek()
}