代码如下:
1 public class MergeSort { 2 3 public static void sort(int [] A,int p, int r) 4 { 5 if(p<r) 6 { 7 int q = (int) Math.floor( (p+r)/2 ); 8 sort(A,p,q); 9 sort(A,q+1,r); 10 merge(A,p,q,r); 11 } 12 return ; 13 14 } 15 public static void merge(int [] A, int p, int q, int r) 16 { 17 int n1 = q-p+1; 18 int n2 = r-q; 19 int [] L = new int[n1]; 20 int [] R = new int[n2]; 21 for(int i=0; i<n1; i++) 22 L[i] = A[p+i]; 23 for(int i=0; i<n2;i++) 24 R[i]=A[q+i+1]; 25 26 int i=0; 27 int j=0; 28 int counter = p; 29 while(i<L.length && j<R.length) 30 { 31 if(L[i]<=R[j]) 32 { 33 A[counter]=L[i]; 34 i++; 35 } 36 else 37 { 38 A[counter]=R[j]; 39 j++; 40 } 41 counter++; 42 } 43 if(i==L.length) 44 { 45 for(int k=j;k<R.length;k++) 46 A[counter++] = R[k]; 47 } 48 else 49 { 50 for(int k=i;k<L.length;k++) 51 A[counter++] = L[k]; 52 } 53 } 54 }
1 public class SumTwoEqual { 2 3 /** 4 * @param args 5 */ 6 public static boolean TestExists(int A[],int X) 7 { 8 MergeSort.sort(A, 0, A.length - 1 ); 9 int i = 0; 10 int j = A.length-1; 11 while(i<j) 12 { 13 if(A[i]+A[j]==X) 14 return true; 15 else if(A[i]+A[j] > X) 16 j--; 17 else 18 i++; 19 } 20 return false; 21 } 22 23 public static void main(String[] args) { 24 int A[] = {1,2,5,7,9,14,25,35,13,15}; 25 boolean a = TestExists(A,22); 26 System.out.println(a); 27 } 28 }
算法思想很简单,就是先排序,然后从两边往中间找。除了上述的解法,还有一种方法是先排序,然后遍历所有元素a,二分查找X-a。
虽然写出了上述的算法,但是说明算法的正确性是个很难的问题。下面我给出一个大致的思路,但是不是很严谨。
我们首先假设所有的元素已经从小到大排序好了,放在数组A[1...n]中,要查询的元素是X。
1、如果A中没有任何两个元素的和是X,那么程序一定会返回false,这是很显然的。
2、所以,问题的关键在于证明:如果A中有两个元素a,b,使得a+b==X(不妨设a<=b),那么程序会保证返回true。
3、而为了证明2,则只需要证明:每一轮迭代开始之前,A[i...j]中一定包含a和b,而A[0...i-1] υ A[j+1...n]一定不包含a和b。
为什么证明了3,就能证明2呢?那是因为每一次迭代A[i...j]长度都会减一(要么i+1,要么j-1),而只要a和b还在A[i...j]中,最终一定会在某一次迭代中发现A[i]==a,A[j]==b,
从而程序返回true。最坏的情况是,迭代一直进行到i+1==j的时候,此时A[i]一定是a,A[j]一定是b。
下面归纳地证明3,即证明:每一轮迭代开始之前,A[i...j]中都包含a和b,而A[0...i-1] υ A[j+1...n]都不包含a和b。
令ik,jk表示第k轮迭代开始之前,i和j的取值。
1、第 1 轮迭代开始之前,A[i1...j1]也就是A[0...n],a和b当然包含在其中,A[0...-1] υ A[n+1...n]是空集,当然不包含a和b。结论成立。
2、假设第 K 轮迭代开始之前,A[ik...jk]中包含a和b,而A[0...ik-1] υ A[jk+1...n]不包含a和b。
那么如果A[ik]+A[jk]==X,那么程序就返回true了。第 K+1 轮迭代不会发生。结论成立。
如果A[ik]+A[jk]>X,按照程序,jk会减1,那么第K+1轮开始之前,ik+1==ik,jk+1==jk-1。下面用反证法证明A[jk]不可能是b(A[jk]当然不可能是a)。因为如果A[jk]是b,那么
X<A[ik]+b<A[ik+1]+b<A[ik+2]+b<...<A[jk-1]+b,那么a就不可能是A[ik...jk-1]中的任何一个元素,这和初始假设A[i...j]中包含a和b矛盾。所以A[jk]不可能是b。所以a和b仍然包含在A[ik+1...jk+1]中。
如果A[i]+A[j]<X,那么A[i]不可能是a(因为b>=a,所以A[i]当然不可能是b)。因为如果A[i]是a,那么
a+A[i+1]<a+A[i+1]<a+A[i+2]<...<a+A[j]<X,那么b就不可能是A[i+1...j]中的任何一个元素,这和初始假设A[i...j]中包含a和b矛盾。
所以,如果A[i]+A[j]>X,按照程序,j会减1,也就是在在第K+1轮迭代开始之前,数据是A[i...j-1],因为A[j]不可能是b,所以A[i...j-1]中仍然包含a和b
如果A[i]+A[j]<X,i会加1,也就是在第K+1轮迭代开始之前,数据是A[i+1...j],因为A[i]不可能是a,所以A[i+1...j]仍然包含a和b。
3、由1和2可知,在每一轮迭代开始之前,A[i...j]中一定包含a和b,而A[0...i-1] υ A[j+1,n]一定不包含a和b。
证明好困难!