《算法导论》笔记 第9章 总结与思考
【思考】
9-1 已排序的i个最大数
给定一个含n个元素的集合,我们希望能用一个基于比较的算法来找出按顺序排列的i个最大元素。
请找出能实现下列每一种方法的、具有最佳的渐进最坏运行时间的算法,并分析各种方法的运行时间(用n和i表示)。
a) 对输入数排序,并列出i个最大的数。
O(nlogn)的排序。
b) 对输入数建立一个优先级队列,并调用EXTRACT-MAX过程i次。
建堆O(n),每次调用O(logn),共O(n+ilogn)
c) 利用一个顺序统计量算法来找到第i个最大元素,然后划分输入数组,再对i个最大数排序。
寻找第i大元素O(n),排序O(ilogi),共O(n+ilogi)
9-2 带权中位数
对分别具有正的权重w1, w2, ... , wn且的n个不同元素x1, x2, ..., xn,带权(下)中位数是满足如下条件的元素xk
a) 论证x1, x2, ..., xn 的中位数即各xi的带权中位数,此处权值 wi=1/n, i=1,2 ..., n。
将wi=1/n带入得
即中位数。
b) 如何通过排序,在O(nlgn)的最坏情况时间内求出n个元素的带权中位数。
先对元素排序,再对权值进行累计,找到第一个xk满足
则xk为带权中位数。
c) 说明如何利用一个线性时间的中位数算法,来在最坏情况Θ(n) 时间内求出n个数的带权中位数。
void prepare(double W[],double SW[],int n) { for (int i=1;i<=n;i++) SW[i] += SW[i-1] + W[i]; } int partition(int A[],int p,int r) { int x = A[r]; int i = p - 1; for (int j=p;j<r;j++) { if (A[j] <= x) { i++; swap(A[i],A[j]); } } swap(A[i+1],A[r]); return i+1; } int randomizedPartition(int A[],int p,int r) { int q = rand()%(r-p+1)+p; swap(A[q],A[r]); return partition(A,p,r); } int randomWeightSelect(int A[],double SW[],int p,int r,double w0) { if (p==r) return A[p]; int q = randomizedPartition(A,p,r); double w1 = SW[q] - SW[p-1]; if (w0==w1) return A[q]; else if (w0<w1) return randomWeightSelect(A,SW,p,q-1,w0); else return randomWeightSelect(A,SW,q+1,r,w0-w1); }
mid = randomWeightSelect(A,SW,1,n,1/2);
邮局选址问题(post-office location problem) 定义如下:已知n个点p1, p2, ..., pn及与它们相联系的权重w1, w2, ..., wn。我们希望能找到一点p(不一定时输入点中的一个),使和式 最小,此处d(a,b)表示点a与b之间的距离。
d)证明带权中位数是一维邮局位置问题的最佳解决方案,其中所有的点都是实数,并且点a与点b之间的距离是d(a,b)=|a-b|。
若xk为带权中位数,要证明xk是最佳解决方案,只需证明
当x>xk时:
若xk>=xi,|x-xi|-|xk-xi|=x-xk
若xk<xi,|x-xi|-|xk-xi|>=-(x-xk)
当x<=xk时:
若xk>xi,|x-xi|-|xk-xi|>=-(xk-x)
若xi>=xk,|x-xi|-|xk-xi|=(xk-x)
均有f(x)>=f(xk),因此带权中位数是一维邮局位置问题的最佳解决方案。
e)找出二维邮局位置问题的最佳解答,其中所有的点都是(x,y)坐标对,并且点a(x1, x2)与点b(x2, y2)之间的距离是Manhattan距离:d(a, b) = |x1 - x2| + |y1 - y2|。
即两个一维选址问题。
9-3 小型顺序统计量
为从n个数字中选出第i个顺序统计量,SELECT在最坏情况下所使用的比较次数T(n)满足T(n)=θ(n),不过隐含在θ符号内的常数相当大。当i相对n来说较小时,我们可以实现一个不同的程序,它以SELECT作为子过程,但最坏情况下所做的比较次数更少。
a) 描述一个能用Ui(n)次比较来找出n个元素的第i小元素的算法,其中
b) 证明:如果i<n/2,则Ui(n)=n+O(T(2i)lg(n/i))。
c) 证明:如果i是个小于n/2的常数,则Ui(n)=n+O(lgn)。
d) 证明:如果对k>=2有i=n/k,那么Ui(n)=n+O(T(2n/k)lgk)。