这是百度的一道面试题。一排N(最大1M)个正整数+1递增,乱序排列,第一个不是最小的,把它换成-1,最小数为a且未知。求第一个被-1替换掉的数原来的值,并分析算法复杂度。
其实这道题并不难,关键是大家能否找出其中的陷阱并解决它。
理解问题:
1. 如果1-10的排序数组打乱顺序之后,我们拿掉其中一个并换成-1,大家能找出来吗?
2. 如果一个等差数列,打乱顺序后,我们拿掉其中一个并换成-1,大家能找出来吗?
3. 如果数据量很大,数据也很大,我们做加法会有问题吗?
从简单问题开始:
大家可以按照以上的思路来逐步优化问题。一般稍微有点算法知识的人想想就会很容易给出以下解法:
设 Sn = a + (a+1) + (a+2) + .........+ (a+n-1) = na +n(n-1)/2
所以替换之前是 Sn。 替换之后得到的S 里少了 a, 多以一个-1, 所以我们得到的Sn与S及a1的关系如下:S + a1 - (-1) = Sn, 即 a1 = Sn - S -1
复杂度为O(n),我们扫描一遍,找出最小的元素 a, 我们得到了S 对吧。
找陷阱,找解决办法
如果有问题,问题出在哪里呢?获取累加和S以及等差数列Sn时可能会出问题。这种问题我们之前就处理过,改加法为减法!!
我们假设构造了另外一个数组b[N]。 用 a, a+1,a+2....a+n-1依次分别减去原数组,得到的差放在该数组里,此求差过程复杂度为O(n), 并对该数组各项求和即可得到Sn-S。好了,如果可行的话,我们其实构造这个数组的必要都没有对吧,每次减去a + N呗,第一元素是a, 第二个a+1, 第三个a+2.
我们还需要证明下这种方法的可行性。
当两个数组元素对应做差的时候, 最差情况下应该是连续n/2个负数或者正数相加,如果不溢出,后面正负混合相加的话肯定不会溢出;这种情况下的最差特殊情况就是,原数列按照降序排列(除了第一项被替换掉了),而我们减时所用数列是增序排列。所得结果将是1个正数,n/2-1个负数,n/2个正数;
- 原数组递减: n, n-1, n-2, n-3,....3,2,1
- 新数组递增: 1, 2, 3, 4,..., n-2, n-1, n
- 做差的数组: n-1, n-3, n-5, n-7,... 1, .... 3+n, 1+n,1-n
这种分析下,我们只用考虑一半的情况,并且替换第一个元素不考虑(因为这是极端的情况,没有替换的情况下都不出现问题,那接下来就不会出现问题了。)
再求做差数组的和
S(n/2) = (n-1) + (n-3) + (n-5)+ .....+ 1 = [(n-1)+1] * n/4 = n^2/4
题目中给定n最大为1M = 1024*1024
那么S(n/2)的最大量级为1024^4 = 2^40
而这个时候如果我们用long类型,即64位,可以存放下该和,我们就能避免溢出问题了。
好了,这道题我们就不上代码了哈。有问题欢迎大家留言。也欢迎大家关注我们的视频教程。