LeetCode问题:寻找缺失的最小正整数(代码逻辑错误排查)
问题分析与修复
先说说你代码的问题:当输入[1]时,循环里只会执行continue跳过,循环结束后没有任何返回语句,导致函数返回undefined。这是因为你处理i=0的情况时,只判断了arr[i] == i+1就跳过,但没处理所有正整数连续时的返回逻辑。
先修复当前代码的bug
把循环结束后的返回逻辑移到循环外面,这样像[1]、[1,2,3]这类所有正整数连续的情况,循环结束后就能返回正确结果:
var firstMissingPositive = function(nums) { nums.sort(compare); var arr = []; for (let i = 0; i < nums.length; i++) { if (nums[i] > 0) arr.push(nums[i]); } if (arr.length === 0) return 1; // 先检查第一个正整数是不是1 if (arr[0] !== 1) { return 1; } // 遍历检查连续的正整数,同时跳过重复值 for (let i = 1; i < arr.length; i++) { if (arr[i] === arr[i-1]) { continue; } if (arr[i] !== arr[i-1] + 1) { return arr[i-1] + 1; } } // 所有正整数都连续,返回最后一个数+1 return arr[arr.length - 1] + 1; }; function compare(a, b) { return a - b; }
注意:当前解法不符合线性时间+常数空间要求
你原本的需求是线性时间(O(n))和常数空间(O(1)),但上面的代码用了sort(时间复杂度O(nlogn)),还额外创建了数组arr(空间复杂度O(n)),不符合要求。下面给你符合要求的最优解法:
var firstMissingPositive = function(nums) { const n = nums.length; // 第一步:把所有不在[1,n]范围内的数替换成n+1 for (let i = 0; i < n; i++) { if (nums[i] <= 0 || nums[i] > n) { nums[i] = n + 1; } } // 第二步:用数组本身当哈希表,标记出现过的正整数 for (let i = 0; i < n; i++) { const num = Math.abs(nums[i]); if (num <= n) { // 把对应索引的数改成负数,代表这个数已经出现过 nums[num - 1] = -Math.abs(nums[num - 1]); } } // 第三步:找到第一个正数的索引,对应的就是缺失的最小正整数 for (let i = 0; i < n; i++) { if (nums[i] > 0) { return i + 1; } } // 如果所有数都是负数,说明1~n都出现了,返回n+1 return n + 1; };
这个解法的核心思路是利用数组的索引作为哈希键,用元素的正负来标记该数是否出现过,全程只遍历数组三次,没有额外开辟空间,完全符合线性时间和常数空间的要求。
内容的提问来源于stack exchange,提问作者Raaz
相关产品推荐
相关产品推荐

