LeetCode第41题思悟——缺失的第一个正数(first-missing-positive)

LeetCode第41题思悟——缺失的第一个正数(first-missing-positive)

知识点预告

  1. 数组下标-数组长度-数组元素值三者关系的理解;
  2. “送”的思路;

题目要求

给定一个未排序的整数数组,找出其中没有出现的最小的正整数。

来源:力扣(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需要满足以下几点:

  1. k为正数,因为k-1>=0;所以k为正数;
  2. k不能大于length,因为k-1<=length-1;
  3. k不在其合适的位置,否则交换没有意义不说,还会出现死循环;

于是我们得到以下条件:

  1. k>0;
  2. k<=length;
  3. 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;
}

差异分析

讲真,优秀解法的空间复杂度不是常数级别吧,实际上,这种思路比较类似桶排序的处理;这是来自提交记录上的解答,但是应该是不符合题目要求的;

知识点小结

  1. 数组下标-数组长度-数组元素值三者关系的理解;
  2. “送”的思路;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值