携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情
题目描述
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。
示例 1:
输入:nums = [1,2,0]
输出:3
示例 2:
输入:nums = [3,4,-1,1]
输出:2
示例 3:
输入:nums = [7,8,9,11,12]
输出:1
提示:
-
1 <= nums.length <= 5 * 105 -
-231 <= nums[i] <= 231 - 1
解题思路
首先通过题目我们可以知道整数数组未排序,且需要找到的是最小的正整数,这成为我们偷懒的巨大绊脚石。
思来想去只能使用点常规手法了。
最简单直接的,我们首要的肯定要对这些整数进行统计,然后为了找到这个最小的正整数,我们还需要从1开始不断的”询问“当前的结果数组中是否存在该整数,一直找到结果数组中不存在并返回,干就完事了。
那么提到统计,一开始我是想到用 javascript 对象的排序属性进行数据的统计。在V8中,对象属性如果是数字,则会按从小到大升序排列。
随后通过 Object.keys 获取当前已存在的所有整数,后面觉得 Object.keys 又要遍历一遍,duck不必,于是就考虑仍旧用对象进行统计,通过属性判断指定的正整数是否存在于当前对象的key中:
- 从
index = 1开始,去obj里检查对象是否具有该属性,index in obj - 如果存在,则返回
index - 否则,
index++,进入下一轮循环
那么我们都知道,javascript 中,通过 in 操作符去寻找一个属性时,是有可能往原型上检索这个属性的,为了避免这个无用的开销,我通过 Object.create(null) 去创建一个纯净对象,这样后续代码中我们就可以不用特意去绕过原型链上的属性,从而直接通过 in 操作符处理。
关于 Object.create(null) 的更多说明,推荐 详解Object.create(null)
通过从1到n的不断检索,最终我们就可以检索到缺失的最小的正整数了。
话不多说,上菜!
题解
/**
* @param {number[]} nums
* @return {number}
*/
var firstMissingPositive = function(nums) {
const lens = nums.length, t = Object.create(null);
for(let i=0; i<lens; ++i) {
t[nums[i]]=1;
}
let index = 1;
while(true) {
if(index in t) {
index++;
continue;
} else {
return index;
}
}
};
结束语
LeetCode 中虚虚实实的,hard 未必困难,middle 未必容易,多挑战不同的题目,锻炼思维,即使不能顶峰相会,也不要陷入泥潭。