《算法导论》习题2.3-7 查找集合S中是否有两个元素和为X---Java实现
2024-10-07 17:36:20
代码如下:
public class MergeSort { public static void sort(int [] A,int p, int r) { if(p<r) { int q = (int) Math.floor( (p+r)/2 ); sort(A,p,q); sort(A,q+1,r); merge(A,p,q,r); } return ; } public static void merge(int [] A, int p, int q, int r) { int n1 = q-p+1; int n2 = r-q; int [] L = new int[n1]; int [] R = new int[n2]; for(int i=0; i<n1; i++) L[i] = A[p+i]; for(int i=0; i<n2;i++) R[i]=A[q+i+1]; int i=0; int j=0; int counter = p; while(i<L.length && j<R.length) { if(L[i]<=R[j]) { A[counter]=L[i]; i++; } else { A[counter]=R[j]; j++; } counter++; } if(i==L.length) { for(int k=j;k<R.length;k++) A[counter++] = R[k]; } else { for(int k=i;k<L.length;k++) A[counter++] = L[k]; } } }
public class SumTwoEqual { /** * @param args */ public static boolean TestExists(int A[],int X) { MergeSort.sort(A, 0, A.length - 1 ); int i = 0; int j = A.length-1; while(i<j) { if(A[i]+A[j]==X) return true; else if(A[i]+A[j] > X) j--; else i++; } return false; } public static void main(String[] args) { int A[] = {1,2,5,7,9,14,25,35,13,15}; boolean a = TestExists(A,22); System.out.println(a); } }
算法思想很简单,就是先排序,然后从两边往中间找。除了上述的解法,还有一种方法是先排序,然后遍历所有元素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。 证明好困难!
最新文章
- jQuery中slice()用法总结
- iOS学习之block
- C#函数式编程
- [转]java.sql.SQLException: 无效的列索引
- HTML5+CSS3的响应式网页设计:自动适应屏幕宽度
- iOS 图片实现马赛克效果
- 小白日记43:kali渗透测试之Web渗透-SqlMap自动注入(一)-sqlmap参数详解TARGET
- ecshop里Ajax.call()方法定义
- 关于MVC EntityType has no key defined的问题
- 图标字体IcoMoon 使用
- vue 父组件与子组件的通信
- soamanager发布的Webservice服务,调用时出现http500报错
- VMware workstation 上克隆CentOS 6.x 系统后网卡无法启动的问题
- monkey事件简介
- Spring是如何校验XML的
- 最短路(bellman)-hdu2066
- 自定义 Git - 配置 Git
- 20170612xlVBA含方框文档填表
- web 前端遇到的问题
- TCP系列19—重传—9、thin stream下的重传