算法与数据结构面试分享(十八)一排N(最大1M)个正整数+1递增,乱序排列,第一个不是最小的,把它换成-1,最小数为a且未知求第一个被

这是百度的一道面试题。一排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位,可以存放下该和,我们就能避免溢出问题了。

好了,这道题我们就不上代码了哈。有问题欢迎大家留言。也欢迎大家关注我们的视频教程。

算法与数据结构

算法与数据结构-微软经典面试题

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值