算法学习-第一个缺失的正整数

题目

给定一个数组A[0...N-1],找到从1开始,第一个不再数组中的正整数。

如3,5,1,2,-3,7,14,8输出4。

分析

解法很多,如下:

1、可以暴力求解,从1遍历到n,每次和数组对比,找到第一个不在数组中的,时间复杂度为O(N2)

2、可以优化一下算法,先排序在进行2分查找,时间复杂度为N*log(N)。

3、因为第一个缺失的正整数肯定小于等于N+1,所以可以申请N个空间,然后遍历原数组,将大于0,小于n的数在新申请的空间中对应的位置做标记,最后遍历申请的空间,找到第一个不在申请空间中的数据,时间复杂度是O(N),空间复杂度是O(N)

4、将找到的元素放到正确位置上,如果最终发现某个元素一直没有找到,则该元素即为所求。循环不变式:如果某命题初始为真,且每次更改后仍然保持该命题为真,则若干次更改后该命题仍然为真。

假定前i-1个数已经找到,并且一次存放在A[1,2,...,i-1]中,继续考察A[i]:

若A[i]<i且A[i]>=1,则A[i]在A[1,2,...,i-1]中已经出现过,可以直接丢弃。若A[i]为负,则更应该丢弃它。

若A[i]>i且A[i]<=N,则A[i]应该置于后面的位置,即将A[A[i]]和A[i]交换。若A[i]>N,由于缺失数据>=N,则A[i]丢弃。若A[A[i]]=A[i],显然不比交换,直接丢弃A[i]即可。

若A[i]=i,则A[i]位于正确的位置上,则i加1,循环不变式扩大,继续比较后面的元素。

算法描述:

若A[i]=i,i加1,继续比较后面的元素。

若A[i]<i或A[i]>N或A[A[i]]=A[i],丢弃A[i]

若A[i]>i,则将A[A[i]]和A[i]交换。

丢弃A[i]即将A[N]赋值给A[i],然后N减1.

下面给出第四种方法的代码

int FirstMissNumber(int* a, int size)
{
	a--;  // 从1开始
	int i = 1;
	while (i <= size)
	{
		if (a[i] == 1)
		{
			i++;
		}
		else if ((a[i] < i) || (a[i] > size) || (a[i] == a[a[i]]))
		{
			a[i] = a[size];
			size--;
		}
		else
		{
			int ntmp = a[a[i]];
			a[a[i]] = a[i];
			a[i] = ntmp;
		}
	}
	return i;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值