习题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. linux ubuntu平台下安装Scrapy

    1.安装Python sudo apt-get install python2.7 python2.7-dev 2.安装pip 下载get-pip.py 选中该文件所在路径,执行下面的命令 sudo ...

  2. cocos2d-js 显示帧序列图中的一帧

    1.flashCC中打开库,在一个元件中右键->Generate Sprite Sheet...设置如下: 2.点Export后得到playerWalk.png和playerWalk.plist ...

  3. 转:Java eclipse下 Ant build.xml实例详解

    在有eclipse集成环境下ant其实不是很重要,但有些项目需要用到,另外通过eclipse来学习和理解ant是个很好的途径,所以写他demo总结下要点,希望能够帮到大家. 一.本人测试环境eclip ...

  4. 一个设置 material design icon的插件工具

    一个设置 material design icon的插件工具 github地址:https://github.com/konifar/android-material-design-icon-gene ...

  5. MFC实现为窗体添加的背景图片

    将一个bmp图片添加到资源中 在资源视图中更改位图资源的ID为IDB_BITMAP_BACKGROUND. 第一种方法: 在Dialog中添加一个Picture Control控件,将Picture ...

  6. hdu_4897_Little Devil I(树链剖分)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4897 题意:有三种操作,1是在树上的两个节点之间的路径改变当前的颜色,2是改变树上有且只有一个端点在u ...

  7. AJAX(XMLHttpRequest)进行跨域请求方法详解(三)

    注意:以下代码请在Firefox 3.5.Chrome 3.0.Safari 4之后的版本中进行测试.IE8的实现方法与其他浏览不同. 3,带验证信息的请求 身份验证是Web开发中经常遇到的问题,在跨 ...

  8. android - 自定义(组合)控件 + 自定义控件外观

    转载:http://www.cnblogs.com/bill-joy/archive/2012/04/26/2471831.html android - 自定义(组合)控件 + 自定义控件外观   A ...

  9. 网页中如何用 CSS 设置打印分页符

    Word 中按 Ctrl + Enter 创建一个分页符,方便打印,其实网页中也可以,用 CSS 的 page-break-after:always;. <p>第 1 页</p> ...

  10. Scroll View 深入

    转载自:http://mobile.51cto.com/hot-430409.htm 可能你很难相信,UIScrollView和一个标准的UIView差异并不大,scroll view确实会多一些方法 ...