LeetCode第41题思悟——缺失的第一个正数(first-missing-positive)
知识点预告
- 数组下标-数组长度-数组元素值三者关系的理解;
- “送”的思路;
题目要求
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-missing-positive
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例
示例 1:
输入: [1,2,0]
输出: 3
示例 2:输入: [3,4,-1,1]
输出: 2
示例 3:输入: [7,8,9,11,12]
输出: 1
说明:你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-missing-positive
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的思路
时间复杂度要求为O(n),那么遍历数组的次数需要为常数;使用常数级别的空间,那么对于数据结构的使用就有了要求,无法使用像Hash Map等统计性质的辅助手段;
排序是一种手段,但是常见的的排序算法,如快速排序等,其时间复杂度也是n log(n);
所以,全部排序并不是首选;但是数组总要有序后,才能找到缺失的那个正数;
考虑没有缺失的正数,并且数据全为正数,那么num[i]=i+1;换言之,数字J应该位于num[J-1];那么我们在一遍遍历数组时,将遇到的数字交换到它该去的位置上,那么当遍历结束时,数字该就位的都已经就位,那么自然我们就可以确定缺失的那个正数了;
所需要确定的问题是,那些数字是可以就位的?换言之,那些数字可以在数组中找到自己合适的位置?为了方便,记当前检查的数字为k,当前的指针为pointer,它应该所在的位置为index=k-1=pointer,则k需要满足以下几点:
- k为正数,因为k-1>=0;所以k为正数;
- k不能大于length,因为k-1<=length-1;
- k不在其合适的位置,否则交换没有意义不说,还会出现死循环;
于是我们得到以下条件:
- k>0;
- k<=length;
- k-1!=pointer;
而k=num[pointer];
实际上,这里说交换并不是很形象,应该是“送”:将当前位置上的数,送到合适的位置上去;如此,理解代码就不难啦;
public static int firstMissingPositive(int[] nums) {
int length;
if(nums==null||(length=nums.length)==0){
return 1;
}
int checkPointer=0;
int temp;
while(checkPointer<length){
while(nums[checkPointer]>0&&nums[checkPointer]<=length&&nums[checkPointer]!=checkPointer+1){
temp=nums[nums[checkPointer]-1];
if(temp!=nums[checkPointer]){
nums[nums[checkPointer]-1]=nums[checkPointer];
nums[checkPointer]=temp;
}else{
break;
}
}
checkPointer++;
}
int missingPointer=0;
for(;missingPointer<length;missingPointer++){
if(nums[missingPointer]!=missingPointer+1){
return missingPointer+1;
}
}
return missingPointer+1;
}
优秀解法
//解法A
public int firstMissingPositive(int[] nums) {
if(nums==null||nums.length==0) return 1;
int[] temp=new int[nums.length];
for(int i=0;i<nums.length;i++){
if(nums[i]<=nums.length&&nums[i]>0)
temp[nums[i]-1]++;
}
for(int i=0;i<nums.length;i++){
if(temp[i]==0) return i+1;
}
return nums.length+1;
}
差异分析
讲真,优秀解法的空间复杂度不是常数级别吧,实际上,这种思路比较类似桶排序的处理;这是来自提交记录上的解答,但是应该是不符合题目要求的;
知识点小结
- 数组下标-数组长度-数组元素值三者关系的理解;
- “送”的思路;