如何优化查找数组中三个最大整数的算法且不使用辅助函数?
原实现存在的潜在问题
你当前的实现逻辑整体思路正确,时间复杂度为O(n),空间复杂度为O(1),优于全数组排序的O(nlogn)方案,但存在一个隐藏bug:
使用!result[index]做非空判断时,0作为JS中的falsy值会导致判断逻辑异常。例如当result中已经存入0时,后续输入比0小的数会触发逻辑或短路,错误覆盖已有的最大值。
方案1:无辅助函数的实现
直接将两个辅助函数的逻辑内联到主函数中,保留原有逻辑的同时去掉外部辅助函数,同时修复上述bug:
function findThreeLargestNumbers(array) { // 初始值设为null,用严格等于判断非空,避免0的falsy问题 const result = [null, null, null]; for (const num of array) { if (result[2] === null || num > result[2]) { // 固定3个元素无需循环,直接手动移位 result[0] = result[1]; result[1] = result[2]; result[2] = num; } else if (result[1] === null || num > result[1]) { result[0] = result[1]; result[1] = num; } else if (result[0] === null || num > result[0]) { result[0] = num; } } // 可选:兼容数组长度不足3的场景,过滤null值 // return result.filter(item => item !== null); return result; } console.log(findThreeLargestNumbers([141, 1, 17, -7, -17, -27, 18, 541, 8, 7, 7]));
方案2:更优的实现版本
该版本是当前需求下的最优实现,时间复杂度仍为O(n)(遍历一次数组是理论下限,不可能有更低的时间复杂度),额外优化点如下:
- 初始值使用负无穷代替null,无需非空判断,天然兼容全负数、包含0的所有边界场景
- 用解构赋值简化移位操作,代码更简洁易读
- 完全去掉不必要的循环逻辑,执行效率更高
function findThreeLargestNumbers(array) { // 按从小到大存储三个最大值,初始为负无穷兼容所有数值场景 let [smallestOfThree, middle, largest] = Array(3).fill(-Infinity); for (const num of array) { if (num > largest) { [smallestOfThree, middle, largest] = [middle, largest, num]; } else if (num > middle) { [smallestOfThree, middle] = [middle, num]; } else if (num > smallestOfThree) { smallestOfThree = num; } } // 可选:数组长度不足3时返回实际存在的最大值,过滤负无穷 // return [smallestOfThree, middle, largest].filter(item => item !== -Infinity); return [smallestOfThree, middle, largest]; } console.log(findThreeLargestNumbers([141, 1, 17, -7, -17, -27, 18, 541, 8, 7, 7]));
内容的提问来源于stack exchange,提问作者dev
相关产品推荐
相关产品推荐

