这是<<算法导论>>中的一题,exercise 2.3-7.

可以这么做:
1) 首先将序列排序,去掉重复的元素.
2) 其次生成一个序列, 该序列中每个元素都是X-原序列中的值, 同样的,去重.
3) 对这两个已经排序好的序列进行合并操作.
4) 如果有两个元素之和为X, 那么在合并的时候必然是相邻的元素.

比如序列 1, 3, 5, 8, X=8, 生成的新序列排序之后就是0, 3, 5, 7.在合并操作时出现两个相邻的3,因此该序列中存在3和5之和为8.

我想的另一种做法:
遍历序列, 每次遍历时将X-序列元素的差放入到另一个新的序列中的合适位置去, 使这个新的序列一直都是有序的.同样的, 每次遍历的时候都在这个新的序列中搜索是否存在当前元素, 由于是有序的, 所以可以采用二分查找的方法.
比如对于序列5,1,8,3, X=8.
首先遍历的元素是5, 此时新的序列是空的,将8-5=3放入到新的序列中.
其次遍历的元素是1, 此时新的序列只有元素3, 将8-1=7放入到新的序列中, 形成3,7的有序序列.
再次遍历的元素是8, 此时新的序列为3,7, 将8-8=0放入到新的序列中, 形成0,3,7的有序序列.
最后遍历的元素是3, 此时新的序列是0,3,7, 查找3成功, 退出.

不过, 很显然, 第二种方法并不能达到题目要求的nlg(n)的要求.但是, 它的优点在于, 不一定非得遍历完序列的所有元素就可以找到答案.

另外,这个题目给我的另一个启示就是,在很多问题中, 排序和搜索算法绝对是最基础的组成部分,你可能不会直接使用到它们, 但是会间接的使用或者借鉴到其中的想法帮助你解决问题.所以, 不管是效率比较低的插入算法也好, 还是快速排序也好, 都要进行研究, 并且掌握其中蕴藏的思想.


posted on 2008-09-29 10:40 那谁 阅读(1245) 评论(5)  编辑 收藏 引用 所属分类: 算法与数据结构
Comments
  • # re: (算法导论习题解ex2.3-7)给定一个整数序列以及一个数X,确定该序列中是否有两个数的和为X
    Ernls
    Posted @ 2008-09-29 11:53
    排序,然后枚举+原序列二分(X-a[i])不行吗?  回复  更多评论   
  • # re: (算法导论习题解exercise2.3-7)给定一个整数序列以及一个数X,确定该序列中是否有两个数的和为X[未登录]
    Uo
    Posted @ 2008-09-30 17:01
    首先nlogn的快排
    其次设一个首指针head 设一个尾指针tail
    while(head!=tail)
    {
    if(*head+*tail < num) head++;
    elseif(*head+*tail>num) tail--;
    else break;

    }

    if (head == tail)std::cout<<"Not found!";
    else
    std::cout<<*head<<" "<<*tail<<std::endl;

    复杂度是o(nlogn+n)=o(nlogn)  回复  更多评论   
  • # re: (算法导论习题解exercise2.3-7)给定一个整数序列以及一个数X,确定该序列中是否有两个数的和为X[未登录]

    Posted @ 2008-09-30 20:09
    @Uo
    嗯,楼上这个方法也不错.
      回复  更多评论   
  • # re: (算法导论习题解exercise2.3-7)给定一个整数序列以及一个数X,确定该序列中是否有两个数的和为X[未登录]
    Uo
    Posted @ 2008-10-01 01:27
    算法导论给出的算法复杂度精确计算应为nlgn+2*n 额外辅助空间为o(n)
    上面那个算法空间复杂度o(1),算法复杂度精确为nlgn+n  回复  更多评论   
  • # re: (算法导论习题解exercise2.3-7)给定一个整数序列以及一个数X,确定该序列中是否有两个数的和为X
    Romeo
    Posted @ 2008-11-11 10:25
    @Uo
    没有回潄,很不严密  回复  更多评论   

标题  
姓名  
主页
验证码 *
内容(提交失败后,可以通过“恢复上次提交”恢复刚刚提交的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
[使用Ctrl+Enter键可以直接提交]
相关链接:
网站导航: