算法导论-趣题集锦(持续更新中)

By:             潘云登

Date:          2009-7-11

Update:      2009-7-17

Email:         intrepyd@gmail.com

Homepage: http://blog.csdn.net/intrepyd

Copyright: 该文章版权由潘云登所有。可在非商业目的下任意传播和复制。

对于商业目的下对本文的任何行为需经作者同意。


写在前面

1.          本文内容取自《算法导论》(2)》,题目多为书中习题。书与习题答案可以从这里(Part1Part2)下载。

2.          所提供的代码都是参考书或习题答案编写,在gcc-4.3.3下简单测试过。

3.          Makefile文件可以参考《Makefile备忘录》中的范例编写。

4.          希望本文对您有所帮助。关于题目的理解和实现,都极有可能包含错误,欢迎随时提出意见和建议。

5.          Enjoy youself J


题目索引

题目1. 两数之和

题目2. 霍纳规则

题目3. 逆序对

 

题目4. 区间计数 

题目5. 选择问题 

题目6. 两数组中位数 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


题目1. 两数之和 (习题2.3-7)

237_sum.c

题目索引

请给出一个运行时间为Θ(n lg n)的算法,使之能在给定一个由n个整数构成的集合S和另一个整数x时,判断出S中是否存在有两个其和等于x的元素。

解题步骤:

1.        对数组S进行归并排序。

2.        构造数组S’={z : z=x-y, y∈S},并排序。由于S已经有序,构造与排序可一并完成。

3.        删除S中重复的元素使仅保留一个,对S’进行同样的操作。

4.        合并SS’,并保证合并后有序,这里可以使用归并排序的思想。

5.        如果在合并后的数组中存在连续两个相同的元素,并且这种元素的个数大于1,那么有解。

设想在合并后的数组中存在连续两个w,则w分别属于SS’,那么S中存在y使得w=x-y,即x=y+w。因此,S中元素wy的和为x

步骤1的运行时间为Θ(n lg n),其余步骤运行时间为Θ(n),因此总的时间代价为Θ(n lg n)

题目2. 霍纳规则 (习题2-3)

23_horner.c

题目索引

对多项式P(x)=∑k=0..n akxk 进行求值。

朴素多项式求值算法,使用双重循环计算多项式的每一项,P(x)=∑k=0..n akxk =a0+a1x+…+anxn,运行时间为Θ(n2)

霍纳规则,将多项式展开为如下形式后,P(x)=∑k=0..n akxk =a0+x(a1+x(a2+…+x(an-1+xan))),用累计计算将时间代价降低为Θ(n)

 

y <- an

i <- n

while(i>=0)

         do y <- ai + x * y

                   i <- i-1

题目3. 逆序对 (习题2-4)

24_inversion.c

题目索引

A[1..n]是一个包含n个不同数的数组。如果在i<j的情况下,有A[i]>A[j],则(i,j)就称为A中的一个逆序对。给出一个算法,它能用Θ(n lg n)的最坏情况运行时间,确定n个元素的任何排列中逆序对的数目。

如果没有运行时间要求,则可以用插入排序的思想进行计数。实际上,逆序对正是基于比较的排序算法在循环过程中试图消除的。也就是说,在排序算法的循环过程中,能够对逆序对进行统计。因此,这里可以修改时间代价为Θ(n lg n)的归并排序,进行求解。

 

题目4. 区间计数 (习题8.2-4)

824_counting.c 

题目索引

请给出一个算法,使之对于给定的介于0k之间的n个整数进行预处理,并能在O(1)时间内,回答出输入的整数中有多少个落在区间[a..b]内。你给出的算法的预处理时间应是Θ(n+k)

本题条件符合计数排序的假设,因此,可以利用计数排序的思想,在线性时间内,对每一个输入元素x,确定出小于x的元素个数C[x]。然后,C[b]-c[a-1]即为落在区间[a..b]内的整数个数。

题目5. 选择问题 (9)

c92_select.c 

题目索引

在平均情况下,以线性时间,在一个由n个元素组成的集合中,选择第i小的元素。

一种用来解决选择问题的分治算法,以快速排序算法为模型。区别在于,这里只要递归地处理划分的一边。

int randomized_select(int *array, int p, int r, int i)

{

    int q, k;

 

    if(p == r)

          return array[p];

 

    q = randomized_partition(array, p, r);

    k = q-p+1;

    if(i == k)

          return array[q];

    else if(i < k)

          return randomized_select(array, p, q-1, i);

    else

          return randomized_select(array, q+1, r, i-k);

}

题目6. 两数组中位数 (习题9.3-8)

938_median.c 

题目索引

X[1..n]Y[1..n]为两个数组,每个都包含n个已排好序的数。给出一个求数组XY中所有2n个元素的中位数的、O(lg n)时间的算法。

O(lg n)的时间要求不允许线性比较数组的每一个元素,只能进行二分查找。假设两数组的中位数位于数组X中,且下标为k,那么数组X中有k个元素小于等于X[k]n-k个元素大于等于X[k],同时,数组Y中有n-k个元素小于等于X[k]k个元素大于等于X[k],并且Y[nk]X[k]Y[nk+1]。因此,本题解法可以使用二分法,从数组XX[(1+n)/2]元素开始,递归检查上述条件是否成立,以确定中位数下标k。如果在数组X中无法确定k,可以对Y进行相同的查找。 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值