《算法导论》习题2.3-7 查找集合S中是否有两个元素和为X---Java实现
代码如下:
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。 证明好困难!
《算法导论》习题2.3-7 查找集合S中是否有两个元素和为X---Java实现的更多相关文章
- 算法导论----VLSI芯片测试; n个手机中过半是好的,找出哪些是好手机
对于分治(Divide and Conquer)的题目,最重要是 1.如何将原问题分解为若干个子问题, 2.子问题中是所有的都需要求解,还是选择一部分子问题即可. 还有一点其实非常关键,但是往往会被忽 ...
- 《算法导论》2.3-7 检查集合中是否存在两数字和为指定的X--算法和证明
习题2.3-7:设计一个算法,对于一个给定的包含n个整数的集合S和另一个给定的整数X,该算法可以在时间内确定S中是否存在两个元素,使得它们的和恰为X. 解题思路:首先应该想到的是先用一个的排序算法对S ...
- 算法导论课后习题解答 第一部分 练习1.1-1->1.1-5
很高兴能和大家一起共同学习算法导论这本书.笔者将在业余时间把算法导论后面的题解以博文的形式展现出来希望能得到大家的支持谢谢.如果有可能我会做一些教学视频免费的供大家观看. 练习题选自算法导论中文第三版 ...
- 【算法导论-36】并查集(Disjoint Set)具体解释
WiKi Disjoint是"不相交"的意思.Disjoint Set高效地支持集合的合并(Union)和集合内元素的查找(Find)两种操作,所以Disjoint Set中文翻译 ...
- 为什么你学不会递归?告别递归,谈谈我的一些经验 关于集合中一些常考的知识点总结 .net辗转java系列(一)视野 彻底理解cookie,session,token
为什么你学不会递归?告别递归,谈谈我的一些经验 可能很多人在大一的时候,就已经接触了递归了,不过,我敢保证很多人初学者刚开始接触递归的时候,是一脸懵逼的,我当初也是,给我的感觉就是,递归太神奇了! ...
- 算法导论(第三版)Exercises2.3(归并排序、二分查找、计算集合中是否有和为X的2个元素)
2.3-1: 3 9 26 38 41 49 52 59 3 26 41 52 9 38 49 57 3 41 52 26 38 57 9 49 3 41 52 26 38 ...
- [置顶] 《算法导论》习题解答搬运&&学习笔记 索引目录
开始学习<算法导论>了,虽然是本大部头,可能很难一下子看完,我还是会慢慢地研究的. 课后的习题和思考有些是很有挑战性的题目,我等蒻菜很难独立解决. 然后发现了Google上有挺全的algo ...
- (搬运)《算法导论》习题解答 Chapter 22.1-1(入度和出度)
(搬运)<算法导论>习题解答 Chapter 22.1-1(入度和出度) 思路:遍历邻接列表即可; 伪代码: for u 属于 Vertex for v属于 Adj[u] outdegre ...
- 算法导论-散列表(Hash Table)-大量数据快速查找算法
目录 引言 直接寻址 散列寻址 散列函数 除法散列 乘法散列 全域散列 完全散列 碰撞处理方法 链表法 开放寻址法 线性探查 二次探查 双重散列 随机散列 再散列问题 完整源码(C++) 参考资料 内 ...
随机推荐
- 1988: Sn 爆long long 的处理方法
题目描述 给你两个数 n, p(0 < n,p <= 10^15); a1 = 1; a2 = 1+2; a3 = 1+2+3; ... an = 1+2+3+...+n Sn ...
- IOS 使用动态库(dylib)和动态加载framework
在iphone上使用动态库的多为dylib文件,这些文件使用标准的dlopen方式来使用是可以的.那相同的在使用framework文件也可以当做动态库的方式来动态加载,这样就可以比较自由的使用appl ...
- 用python计算md5,sha1,crc32
Linux下计算md5sum,sha1sum,crc: 命令 输出 $md5sum hello f19dd746bc6ab0f0155808c388be8ff0 hello $sha1sum hel ...
- 尝试在数据库 5 中提取逻辑页 (1:1640) 失败。该逻辑页属于分配单元XXX ,而非 XXX。
此信息表明数据库或表 已经部分损坏可以通过以下步骤尝试修复: 1. DBCC CHECKDB 重启服务器后,在没有进行任何操作的情况下,在SQL查询分析器中执行以下SQL进行数据库的修复,修复数据库存 ...
- Ubuntu vim显示行号语法高亮自动缩进
配置文件名为Ubuntu vimrc在Fedora中vim的配置文件存放在/etc目录中,配置文件名为Ubuntu vimrc在终端 输入以下命令来编辑Ubuntu vimrc配置文件:sudo vi ...
- gc CMSMaxAbortablePrecleanTime
https://blogs.oracle.com/jonthecollector/ 链接打不开了,我记得里边说,这个参数是指定vm试图在它指定的时间间隔内等到一次小垃圾回收...minor gc, g ...
- subversion javahl
新建android项目时,总是说"javahl, require version 1.8"云云. dpkg -l | grep libsvn-java1.6 apt-get upd ...
- 转:sqlplus与shell互相传值的几种情况
sqlplus与shell互相传值的几种情况 情况一:在shell中最简单的调用sqlplus $cat test.sh #!/bin/sh sqlplus oracle/oracle@oracle& ...
- FusionCharts参数大全及详细说明(中文)
概述:本文主要整理了FusionCharts图表控件所包含的各类参数(中文说明),包含了图表,字体,网格,数字格式等参数,便于大家在FusionCharts使用过程中查找所需要的各类参数. 本文主要整 ...
- css盒子
<html><head lang="en"> <meta charset="UTF-8"> <title>< ...