难点在于限制了时间复杂度和空间复杂度。
假如没有限制那么第一种方法优先想到建立一个哈希表,将所有元素全部存在一个哈希表中然后从[1,n]开始查找就可以,可惜哈希表的时间复杂度和空间复杂度皆为O(n),不合题意。
第二种也不符合题意的方法:二分查找,根据题意我们只需要在[1,n]中从小到大一次查找,但是这种查找方式肯定是需要排序的,所以这是一个空间复杂度为O(1),时间复杂度为O(NlogN)的方法。
结合两种方法我们需要在原数组上维护一个哈希表,怎么维护这个哈希表呢?我们可以发现当前元素n正确的位置永远是n-1,用这个条件将两个数组元素交换位置就可以维护了。
// @lc code=start
/**
* @param {number[]} nums
* @return {number}
*/
let swap=function(nums,i,j){
let tmp
tmp=nums[i]
nums[i]=nums[j]
nums[j]=tmp
}
var firstMissingPositive = function (nums) {
let n=nums.length;
//将元素组中的元素按顺序排列好,把数组当成一个哈希表,从左往右的查询当前元素是否为索引+1
for(let i=0;i<n;i++){
//当前元素必须要大于1且在要小于数组长度,并且交换前要确认是否在正确位置
while(nums[i]>=1 && nums[i]<=n && nums[nums[i]-1]!=nums[i]){
swap(nums,i,nums[i]-1)
}
}
for(let i=0;i<n;i++){
if(nums[i]!=i+1){
return i+1
}
}
//极端情况每一个位置都对
return n+1
};