面试题之缺失的数字分析

缺失的数字分析

原题

给定一个无序的整数数组,怎么找到第一个大于0,并且不在此数组的整数。比如[1,2,0] 返回 3, [3,4,-1,1] 返回 2。最好能O(1)空间和O(n)时间。

分析

首先数组是无序的,找到第一个大于0且不在数组中的元素,就是要找到大于0且不在数组中的最小的整数。要怎么处理呢?要找到最小的,不妨尝试从小到 大排序,然后从1开始,查找是否在数组中,可以利用二分查找。这样整体的时间复杂度是O(nlogn),空间复杂度是O(1)。

离题目的要求,还差一些。如何改进呢?针对排序好的数组,我们做如下的观察:

  • 当缺失的数字为1的时候,A[0]<=0, A[1] != 1

  • 当缺失的数字为2的时候,A[0]<=0, A[1] = 1, A[2] != 2

  • 当缺失的数字为3的时候,A[0]<=0, A[1] = 1, A[2] = 2, A[3] != 3

通过上面的观察,可以发现,其实并不需要整个数组是有序的,只需要让数组中的0<A[i]<n的,能够还原到A[i]的位 置,就像缺失3的时候,使得A[1] = 1, A[2] = 2,而且,这两个一定是这样的。后面的序就无需理会了。能够做到,不排序,就实现位置的还原么?且看如下的算法:

由后到前扫描数组:

  1. 如果A[i]=n,则continue;

  2. 如果A[i]=A[A[i]],则continue;

  3. 如果0<A[i]<n,那么可以还原,则swap(A[i], A[A[i]]),然后跳转到步骤2

然后,数组中如果存在0<A[i]<n的,已经保证A[i]=i了。此时:

  • 从1开始遍历,如果A[i]!=i,则i就是要找的数

  • 如果遍历完,没有找到,则说明i从[1,n-1],都有A[i]=i,那么这个时候就看A[0],如果A[0]是n,则返回n+1,如果A[0]不是n,则返回n,即可。

上面算法的时间复杂度是O(n)么?有的同学会想,在swap之后,仍然到第2步,可能还会出现交换,所以时间复杂度要高于O(n)。但实际上,swap之后,是会发生再次的交换,但我们可以保证,每一次交换,都会使得一个数字还原,即A[i]=i,再一次交换,会让一个新的数字还原。 假设数组中,可以还原的数字个数为k,则需要交换k次,k最多为n-1。这里要很小心,因为总的交换次数是k,并不是对于每一个元素,都会产生k次交换。 如果是后者,总的时间复杂度就是O(kn)了,但因为总的交换次数是k,所以总的时间复杂度是O(n+k),就是O(n)。

【分析完毕】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值