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,那么就是存在。