习题2.3-7:设计一个算法,对于一个给定的包含n个整数的集合S和另一个给定的整数X,该算法可以在时间内确定S中是否存在两个元素,使得它们的和恰为X。

解题思路:首先应该想到的是先用一个的排序算法对S中的元素进行排序。接下来有两种处理思路,第一种思路是遍历已经排好序了的S中的所有元素a,并采用

二分查找的方法在S中查找X-a,如果能够找到,那么说明S中确实存在两个元素的和为X,算法终止。这种思路很显然是满足的限制要求的;第二种思路是我自己

想出的一个算法,这个算法也很简单,但是其正确性不是很好证明。

思路1:

CheckSum( A[1…n] , X )
1    MergeSort( A ) //从小到大排序
2    for i = 1 to n
3        if  BinarySearch( A[1…n] , X-A[i] ) != –1 //假设BinarySearch在找不到指定元素的时候返回-1
4              return true
5    return false

思路2:

CheckSum( A[1…n] , X)
1    MergeSort( A ) //从小到大排序
2    i = 1
3    j = n
4    while( i < j)
5        if( A[i] + A[j] == X)
6             return true
7        else if( A[i] + A[j] > X)
8             j--
9        else if( A[i] + A[j] < X)
10           i++
11   return false

算法正确性证明:

思路1的正确性是显而易见的;思路2的正确性就不那么直观,其可能令人感到困惑的地方在于:思路2会不会漏掉某些情况?下面开始思路2的证明,

但是因为我也是初学,证明过程不是很严谨和规范。

首先,假设S中“不”包含两个和为X的元素,那么思路2的第5行的测试条件永远不会成真,那么最终算法一定会返回false。因此,证明思路2的正确性

便转化成证明:

若S中存在两个元素a和b,使得a+b==X,那么算法一定会返回true。(*)

为了证明(*)成立,下面首先证明思路2的算法在执行过程中满足如下的特性:

若S中存在两个元素a和b,使得a+b==X(不妨设a<=b),则在思路2的算法执行过程汇中,每一次迭代开始之前(即算法第4行执行之前),A[i…j]都包含a和b。(#)

下面采用归纳法证明(#)的成立:(令 ik,jk 分别表示第 k 轮迭代开始之前 i 和 j 的取值,A[ik…jk]表示第k轮迭代开始之前的A[i…j])

证明:
1、第 1 轮迭代开始之前,i1=1,j1=n。A[ik…jk]即为A[1…n],a和b很显然包含在A[1…n]中,结论成立。
2、若第 k 轮迭代开始之前,A[ik…jk]包含a和b。则按照算法的执行步骤:
     (1)如果A[ik]+A[jk]==X,算法返回true,算法终止。
     (2)如果A[ik]+A[jk] > X,算法使得jk值减1,即第 k+1 轮迭代开始之前,ik+1 = ik,jk+1 = jk - 1。下面证
             明A[jk]不可能是a或者b中的任何一个: 
             (2.1)因为a<b,且A[ik…jk]包含a和b,所以A[jk]不可能是a。
             (2.2)假设A[jk]等于b,因为A[]是从小到大排序的,所以,必然有:
                        A[jk]+A[jk-1] > A[jk]+A[jk-2] > A[jk]+A[jk-3] > … > A[jk]+A[ik+1] >A[jk]+A[ik] > X,即:
                        b+A[jk-1] > b+A[jk-2] > b+A[jk-3] > … > b+A[ik+1] >b+A[ik] > X
                        也就是说a不可能是A[ik…jk-1]中的任何一个元素,这和前提:A[ik…jk]包含a和b 矛盾,所以假
                        设错误,所以A[jk]不是b。
              因为A[ik…jk]中包含a和b,而又已经证明A[jk]不是a或者b,又ik+1 = ik,jk+1 = jk - 1 ,所以,在第k+
              1轮迭代开始之前,A[ik+1…jk+1]一定包含a和b。
     (3)如果A[ik]+A[jk] < X,同理可证第k+1轮迭代开始之前A[ik+1,jk+1]一定包含a和b。 
3、由1、和2、可知,每一次迭代开始之前,A[i…j]都包含a和b。

现在(#)已经得到证明,而由(#)证(*)是很直观的。因为A[i…j]中始终包含a和b,并且每一次迭代A[i…j]的规模小一,所以,最坏的情况是迭代一直执行到i+1=j的

时候,因为此时A[i,j]包含a和b,所以A[i]一定是a,A[j]一定是b,算法检测到A[i]+A[j] = a+b=X,算法返回true。

总结:以上便是全部内容,从理论上讲思路2应该要比思路1要快(虽然它们都是)。但是很明显地,思路1的正确性更加直观。

《算法导论》2.3-7 检查集合中是否存在两数字和为指定的X--算法和证明的更多相关文章

  1. [算法导论]练习2-4.d求排列中逆序对的数量

    转载请注明:http://www.cnblogs.com/StartoverX/p/4283186.html 题目:给出一个确定在n个不同元素的任何排列中逆序对数量的算法,最坏情况需要Θ(nlgn)时 ...

  2. leetcode-1 Two Sum 找到数组中两数字和为指定和

     问题描写叙述:在一个数组(无序)中高速找出两个数字,使得两个数字之和等于一个给定的值.如果数组中肯定存在至少一组满足要求. <剑指Offer>P214(有序数组) <编程之美& ...

  3. 《算法导论》— Chapter 9 中位数和顺序统计学

    序 在算法导论的第二部分主要探讨了排序和顺序统计学,第六章~第八章讨论了堆排序.快速排序以及三种线性排序算法.该部分的最后一个章节,将讨论顺序统计方面的知识. 在一个由n个元素组成的集合中,第i个顺序 ...

  4. 算法导论 之 红黑树 - 删除[C语言]【转】

    转自:https://blog.csdn.net/qifengzou/article/details/17608863 作者:邹祁峰 邮箱:Qifeng.zou.job@hotmail.com 博客: ...

  5. not(expr|ele|fn)从匹配元素的集合中删除与指定表达式匹配的元素

    not(expr|ele|fn) 概述 从匹配元素的集合中删除与指定表达式匹配的元素   参数 exprStringV1.0 一个选择器字符串.深圳dd马达 elementDOMElementV1.0 ...

  6. C#经典算法实践,回顾往生,更是致敬《算法导论》

    该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/666 访问. 概述 本系列博文将会向大家介绍本人在钻研<算法导论 ...

  7. 集合中list、ArrayList、LinkedList、Vector的区别、Collection接口的共性方法以及数据结构的总结

    List (链表|线性表) 特点: 接口,可存放重复元素,元素存取是有序的,允许在指定位置插入元素,并通过索引来访问元素 1.创建一个用指定可视行数初始化的新滚动列表.默认情况下,不允许进行多项选择. ...

  8. list<T>集合中的Remove()、RemoveAt()、RemoveRange()、RemoveAll()的用法

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  9. 《算法导论》习题2.3-7 查找集合S中是否有两个元素和为X---Java实现

    代码如下: public class MergeSort { public static void sort(int [] A,int p, int r) { if(p<r) { int q = ...

随机推荐

  1. Swift - UIPasteboard剪贴板的使用详解(复制、粘贴文字和图片)

    转载自:http://www.hangge.com/blog/cache/detail_1085.html UITextField.UITextView组件系统原生就支持文字的复制,但有时我们需要让其 ...

  2. Loadrunner之脚本的调试和保存(六)

    一.调试脚本 脚本录制完毕后,按F5键或单击菜单上的RUN按钮,可以运行脚本.       在VIRTUAL USER GENERATOR中运行脚本的作用,主要是查看录制的脚本能否正常通过,如果有问题 ...

  3. jQuery checkbox 全选

    jQuery 1.6版本以后 if($("#id").attr("checked")) 不能返回 ture 和 false 高版本中jQuery 提供prop ...

  4. HDU 5768 Lucky7 (容斥原理 + 中国剩余定理 + 状态压缩 + 带膜乘法)

    题意:……应该不用我说了,看起来就很容斥原理,很中国剩余定理…… 方法:因为题目中的n最大是15,使用状态压缩可以将所有的组合都举出来,然后再拆开成数组,进行中国剩余定理的运算,中国剩余定理能够求出同 ...

  5. POJ 3307 Smart Sister

    先找出所有的数,排序,然后o(1)效率询问 #include<cstdio> #include<cstring> #include<cmath> #include& ...

  6. 微信小程序页面-页面跳转失败WAService.js:3 navigateTo:fail url not in app.json

    微信小程序新建页面的要素一是新建的文件名称和其子文件的名称最好一致,不然容易出问题,在小程序页面跳转中如果出现WAService.js:3 navigateTo:fail url not in app ...

  7. 在线的代码托管平台 coding.net ===中国扩展版github

    coding.net 是国内新兴的一个项目管理平台,功能主要包括:代码托管.在线运行环境.监控代码质量,兼有一定的社交功能. 在线运行环境支持Java.Ruby.Node.js.PHP.Python. ...

  8. 监控redis进程,如果没有自动重启

    监控redis进程,如果没有自动重启 #Time:2016-01-22#Version:1.0 #Author:chh-huang #设置环境变量source /etc/profile#source ...

  9. linux文件分割(将大的日志文件分割成小的)【转载】

    linux文件分割(将大的日志文件分割成小的)linux下文件分割可以通过split命令来实现,可以指定按行数分割和安大小分割两种模式.Linux下文件合并可以通过cat命令来实现,非常简单. 在Li ...

  10. 关于127.0.0.1与localhost

    127.0.0.1是不会经过防火墙的,而localhost是要通过防火墙取地址的.