LeetCode三数之和代码疑问:hasSimularArray的return未正常退出?
3Sum问题中hasSimularArray函数return表现异常的原因
你在实现3Sum问题时,发现调用hasSimularArray函数时,感觉函数内的return true没有正常终止执行,像递归一样持续运行。但单独测试hasSimularArray是正常的,调试也没找到线索。
你的代码如下:
function threeSum(nums: number[]): number[][] { const tripletsResult = []; nums.sort((a, b) => a - b); for (let i = 0; i < nums.length - 2; i++) { let j = i + 1; let k = nums.length - 1; while (j < k) { const possibleResultEl = [nums[i], nums[j], nums[k]]; const threeNumsSum = nums[i] + nums[j] + nums[k]; if (threeNumsSum === 0) { const hasVal = hasSimularArray(tripletsResult, possibleResultEl); if (!hasVal) { tripletsResult.push(possibleResultEl); } } else if (threeNumsSum < 0) { j++; } else { k--; } } } return tripletsResult; } function hasSimularArray(mainArr: number[][], searchedArr: number[]) { if (mainArr.length === 0) { return false; } const searchArrayStr = JSON.stringify([...searchedArr].sort()); for (let el of mainArr) { const elArrayStr = JSON.stringify([...el].sort()); if (elArrayStr === searchArrayStr) { return true; } } return false; } console.log(threeSum([0, 3, 0, 1, 1, -1, -5, -5, 3, -3, -3, 0]));
问题根源
hasSimularArray函数本身没有问题,它的return语句完全正常——只要找到匹配的数组,就会立即终止函数并返回true。你看到的"持续运行"现象,是threeSum的循环逻辑缺陷导致的:
- 虽然你对
nums做了排序,但没有跳过重复的nums[i]。比如当nums[i]和前一个元素相同时,继续处理会生成完全相同的三元组,导致反复调用hasSimularArray检查重复。 - 找到和为0的三元组后,也没有跳过
j和k指向的重复元素,这会让while循环继续生成相同的三元组,再次触发hasSimularArray的调用。
这些重复的调用让你误以为是hasSimularArray没有终止,实际上每次调用都正常结束了,只是被反复触发而已。
修复方案
修改threeSum的循环逻辑,跳过重复元素,同时可以直接去掉效率低下的hasSimularArray函数:
function threeSum(nums: number[]): number[][] { const tripletsResult = []; nums.sort((a, b) => a - b); for (let i = 0; i < nums.length - 2; i++) { // 跳过重复的基准元素 if (i > 0 && nums[i] === nums[i - 1]) continue; let j = i + 1; let k = nums.length - 1; while (j < k) { const sum = nums[i] + nums[j] + nums[k]; if (sum === 0) { tripletsResult.push([nums[i], nums[j], nums[k]]); // 跳过j指向的重复元素 while (j < k && nums[j] === nums[j + 1]) j++; // 跳过k指向的重复元素 while (j < k && nums[k] === nums[k - 1]) k--; // 移动指针继续寻找 j++; k--; } else if (sum < 0) { j++; } else { k--; } } } return tripletsResult; } console.log(threeSum([0, 3, 0, 1, 1, -1, -5, -5, 3, -3, -3, 0]));
修改说明
- 循环
i时,跳过和前一个元素相同的值,避免重复处理同一基准的三元组。 - 找到和为0的三元组后,跳过
j和k的重复元素,确保不会生成重复的结果。 - 去掉
hasSimularArray函数,既解决了你的困惑,又大幅提升了代码性能(原方法用JSON.stringify做重复检查,时间复杂度极高)。
内容的提问来源于stack exchange,提问作者Mini elephant
相关产品推荐
相关产品推荐

