题目
分析
看到查找某个数,就应该考虑哈希。这里用HashMap不合适,输入量本身就是一个数组,可以借助于数组的下标来达到哈希的效果。可以在原数组进行操作;也可以新开辟一个数组进行操作。新开辟数组代码实现会更简单哦。
- 首先正整数是从1开始的,假设数组长度为n, 那么缺失的第一个最大正整数为n+1, 即数组中已经存储了1到n的值,且没有重复元素。那么首先,我们应该先将数组中大于n+1的数和小于1的数给找出来,然后从剩下的数中来判断缺失的第一个正整数是谁?因为我们要向借助于数组的下标来达到Hash索引的效果,那么就需要将各个元素的值设置的0-n-1之间,而最小正整数为1 ,数组的下标又是从0开始的,因此将数组下标0用于表示元素n.
- OK了。现在要解决的问题就是将不在1-n之间的数转换到1到n之间,那么转换为几呢?? 转换为1 !!! 为什么呢? 因为我们可以先遍历一遍数组,看是否又元素1的存在,如果不存在,也不用后续的操作的,直接返回1即可。 如果转换为别的数字是不会有这个效果的。
- 然后依次遍历,将元素值与数组的下标对应,比如,元素值2,找到下标为2的元素,将其取反,表示元素2存在于数组中,前面已经说了元素n与下标0对应。这样存在于数组中的元素就会将其对应的下标中的元素取反了,转换为了负数,我们就可以依次查看哪一下标中的元素值还是正数,就说明此下标正是缺失的第一个正整数,因为元素中不存在该下标值,故未取反。如果都是负数,那么说明1到n都在数组中,返回n+1即可。
代码
利用原数组:
class Solution {
public int firstMissingPositive(int[] nums) {
boolean flag=true;
for(int i=0;i<nums.length;i++)
if(nums[i]==1){
flag=false;
break;
}
if(flag)
return 1;
if(nums.length==1)
return 2;
for(int i=0;i<nums.length;i++)
if(nums[i]<=0||nums[i]>nums.length)
nums[i]=1;
for(int i=0;i<nums.length;i++){
int a=Math.abs(nums[i]);
if(a==nums.length)
nums[0]=-Math.abs(nums[0]);
else
nums[a]=-Math.abs(nums[a]);
}
for(int i=1;i<nums.length;i++){
if(nums[i]>0)
return i;
}
if(nums[0]>0)
return nums.length;
return nums.length+1;
}
}
开辟新数组:
class Solution {
public int firstMissingPositive(int[] nums) {
int []a=new int[nums.length+1];
for(int i=0;i<nums.length;i++){
if(nums[i]>0&&nums[i]<=nums.length)
a[nums[i]]=1;
}
for(int i=1;i<a.length;i++){
if(a[i]!=1)
return i;
}
return a.length;
}
}