算法intuition之-给定一个整形数组,找出其中两个数之和为指定数

http://www.fengchang.cc/post/55

这题本没什么难度,然而看到某书上说:

这种证明是不对的,因为完全没有考虑错过的情况,是不严谨或者胡乱做假设前提的论证方式,故出一篇勘误。

intuition1: 在无序的情况下,必须两两比较才能确定最终结果,那么结果必然是O(n2)的时间复杂,这个不好。

intuition2:在有序的情况下,可以用两个指针初始化为头和尾,即为i和j,那么n[i]+n[j]可以得出一个值,这个值跟给定值M有三种情况

1, M==n[i]+n[j]

2, M>n[i]+n[j]

3, M<n[i]+n[j]

第一种情况就不用说了,直接得到答案,

第二种情况,意味着两者之和太小了,那么需要增大,增大的直觉方法有两种,要么向右移动i,要么向右移动j。假设最终的一个结果是m,n(也就是i移动m位,j移到n位)那么我们设定一个原则,凡是第二种情况出现时,就向右移动i, 凡是第三种情况出现时,就想左移动j,那么按照这种原则是否会出现m,n被错过的情况?也就是说例如出现i先越过了m,但j还在n的后面,或者另一种情况,j先越过了n,然而j还在m左边的情况?可以证明,不可能!

证明如下:从m,n在i,j之间的状态说起,假设i先达到了m(另一种情况是j先达到了n,根据对称性,这两者没有本质区别,但至少会发生两者中的一种),那么此时j尚未达到n,则必然出现第三种情况,那么根据我们的移动原则,j就必然想左移动,并且,只要没有达到n,这个动作会一直持续直到达到n,从而不会错过n,根据对称性,另一种情况同样如此,所以根据以上设定的移动规则,必然不会错过可能出现的 答案。

还有一种空间换时间的方式,用hashmap来记录值和index,这样只要遍历一遍,并用Hashmap直接判定是否存在另一个下标。

但是这种方法有一个问题,就是当存在相同值时,并且恰好求和的两个数是同值不同位时,必然会出问题。修正方式是hashmap中的value用list或者set来存储,那么如果最终两个值对应的index set不同,或者index set相同但set size>1,那么就是存在。

猜你喜欢

转载自blog.csdn.net/xunileida/article/details/81879419