By: 潘云登
Date: 2009-7-11
Update: 2009-7-17
Email: intrepyd@gmail.com
Homepage: http://blog.youkuaiyun.com/intrepyd
Copyright: 该文章版权由潘云登所有。可在非商业目的下任意传播和复制。
对于商业目的下对本文的任何行为需经作者同意。
写在前面
1. 本文内容取自《算法导论》(第2版)》,题目多为书中习题。书与习题答案可以从这里(Part1,Part2)下载。
2. 所提供的代码都是参考书或习题答案编写,在gcc-4.3.3下简单测试过。
3. Makefile文件可以参考《Makefile备忘录》中的范例编写。
4. 希望本文对您有所帮助。关于题目的理解和实现,都极有可能包含错误,欢迎随时提出意见和建议。
5. Enjoy youself J
|
|
| |
|
|
| |
|
|
| |
|
|
| |
|
|
| |
|
|
| |
|
|
| |
|
|
|
请给出一个运行时间为Θ(n lg n)的算法,使之能在给定一个由n个整数构成的集合S和另一个整数x时,判断出S中是否存在有两个其和等于x的元素。
解题步骤:
1. 对数组S进行归并排序。
2. 构造数组S’={z : z=x-y, y∈S},并排序。由于S已经有序,构造与排序可一并完成。
3. 删除S中重复的元素使仅保留一个,对S’进行同样的操作。
4. 合并S和S’,并保证合并后有序,这里可以使用归并排序的思想。
5. 如果在合并后的数组中存在连续两个相同的元素,并且这种元素的个数大于1,那么有解。
设想在合并后的数组中存在连续两个w,则w分别属于S和S’,那么S中存在y使得w=x-y,即x=y+w。因此,S中元素w和y的和为x。
步骤1的运行时间为Θ(n lg n),其余步骤运行时间为Θ(n),因此总的时间代价为Θ(n lg n)。
对多项式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 |
设A[1..n]是一个包含n个不同数的数组。如果在i<j的情况下,有A[i]>A[j],则(i,j)就称为A中的一个逆序对。给出一个算法,它能用Θ(n lg n)的最坏情况运行时间,确定n个元素的任何排列中逆序对的数目。
如果没有运行时间要求,则可以用插入排序的思想进行计数。实际上,逆序对正是基于比较的排序算法在循环过程中试图消除的。也就是说,在排序算法的循环过程中,能够对逆序对进行统计。因此,这里可以修改时间代价为Θ(n lg n)的归并排序,进行求解。
824_counting.c |
请给出一个算法,使之对于给定的介于0到k之间的n个整数进行预处理,并能在O(1)时间内,回答出输入的整数中有多少个落在区间[a..b]内。你给出的算法的预处理时间应是Θ(n+k)。
本题条件符合计数排序的假设,因此,可以利用计数排序的思想,在线性时间内,对每一个输入元素x,确定出小于x的元素个数C[x]。然后,C[b]-c[a-1]即为落在区间[a..b]内的整数个数。
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); } |
938_median.c |
设X[1..n]和Y[1..n]为两个数组,每个都包含n个已排好序的数。给出一个求数组X和Y中所有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[n−k]≤X[k]≤Y[n−k+1]。因此,本题解法可以使用二分法,从数组X的X[(1+n)/2]元素开始,递归检查上述条件是否成立,以确定中位数下标k。如果在数组X中无法确定k,可以对Y进行相同的查找。