题目
题解
暴力法(哈希表)
很神奇的一件事是,直接暴力这道题也能通过!
把nums内所有数字存入哈希表中,接着再从1开始枚举正整数,看哪个数字不在哈希表中即返回。
class Solution {
public int firstMissingPositive(int[] nums) {
int n=nums.length;
Set<Integer>set=new HashSet<>();
for(int i=0;i<n;i++){
set.add(nums[i]);
}
for(int i=1;i<=n;i++){
if(!set.contains(i))
return i;
}
return n+1;
}
}
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n),不符合题目中常数级别额外空间的要求
原地哈希
- 检查1是否存在于数组中。如果没有,则缺失1,直接返回。
- 将负数,0,大于n的数替换为1。此时数组中的数均为正数。
- 遍历数组。当读到数字a时,给第a个元素(下标a-1)加上负号。
注意重复元素:只能改变一次符号。由于下标从0开始,数字a索引值为a-1。
- 再次遍历数组。返回第一个正数元素的下标+1。
- 如果之前的步骤中没有发现nums中有正数元素,则返回n+1。
总的来说,就是用原数组nums记录某个元素是否出现过,出现过则对应元素下标就取负,所以叫“原地”哈希。
class Solution {
public int firstMissingPositive(int[] nums) {
int n=nums.length;
boolean flag=true;
for(int i=0;i<n;i++){
if(nums[i]==1){
flag=false;
break;
}
}
if(flag)
return 1;
for(int i=0;i<n;i++){
if(nums[i]==0||nums[i]<0||nums[i]>n)
nums[i]=1;
}
for(int i=0;i<n;i++){
int a=Math.abs(nums[i]);
nums[a-1]=-Math.abs(nums[a-1]);
}
for(int i=0;i<n;i++){
if(nums[i]>0)
return i+1;
}
return n+1;
}
}
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)