如何正确处理双指针循环中的边界更新以避免无限循环

本文解析 leetcode「三数之和」问题中因未更新双指针导致的无限循环问题,重点说明 `return` 语句作用域仅限当前函数、不会影响外层逻辑,并提供修复方案与最佳实践。

在实现 threeSum 时,一个常见但隐蔽的错误是:当找到和为 0 的三元组后,未推进双指针 j 和 k,导致 while (j

问题根源在于主循环逻辑:

while (j < k) {
  const threeNumsSum = nums[i] + nums[j] + nums[k];
  if (threeNumsSum === 0) {
    const hasVal = hasSimularArray(tripletsResult, [nums[i], nums[j], nums[k]]);
    if (!hasVal) tripletsResult.push([nums[i], nums[j], nums[k]]);
    // ❌ 缺失关键操作:j 和 k 未更新 → 下一轮迭代仍计算相同索引!
  } else if (threeNumsSum < 0) {
    j++; // ✅ 正确:和太小 → 左指针右移增大值
  } else {
    k--; // ✅ 正确:和太大 → 右指针左移减小值
  }
}

当 threeNumsSum === 0 时,若不更新 j 或 k,下一次循环 j 和 k 不变,possibleResultEl 和 threeNumsSum 完全重复,循环永不停止。

正确修复方式(必须同时移动双指针):

if (threeNumsSum === 0) {
  const triplet = [nums[i], nums[j], nums[k]];
  if (!hasSimularArray(tripletsResult, triplet)) {
    tripletsResult.push(triplet);
  }
  // ✅ 关键:跳过已处理的组合,避免重复且打破循环
  j++;
  k--;
}

⚠️ 注意事项:

  • 即使使用 hasSimularArray 去重,也不能替代指针推进——去重是业务逻辑,而 j++/k-- 是循环终止的必要条件;
  • 若数组含重复元素(如 [0,0,0,0]),还需额外跳过相邻重复值(while (j
  • hasSimularArray 本身效率较低(时间复杂度 O(n) × JSON 序列化开销),生产环境建议改用 Set + 字符串键(如 nums[i]+'_'+nums[j]+'_'+nums[k])或排序后哈希优化。

总结:return 永远只退出当前函数作用域;双指针算法中,每次满足条件分支都必须确保循环变量发生有效变

,这是避免无限循环的根本原则。