算法导论第三版第七章课后答案

7.1-1 参照图7-1的方法,说明PARTITION在数组A={13,9,9,5,12,8,7,4,21,2,6,11}上的操作过程。

A={13,19,9,5,12,8,7,4,21,2,6,11}

  ={13,19,9,5,12,8,7,4,21,2,6,11}

  ={13,19,9,5,12,8,7,4,21,2,6,11}

  ={9,19,13,5,12,8,7,4,21,2,6,11}

  ={9,5,13,19,12,8,7,4,21,2,6,11}

  ={9,5,13,19,12,8,7,4,21,2,6,11}

  ={9,5,8,19,12,13,7,4,21,2,6,11}

  ={9,5,8,7,12,13,19,4,21,2,6,11}

  ={9,5,8,7,4,13,19,12,21,2,6,11}

  ={9,5,8,7,4,13,19,12,21,2,6,11}

  ={9,5,8,7,4,2,19,12,21,13,6,11}

  ={9,5,8,7,4,2,6,12,21,13,19,11}

  ={9,5,8,7,4,2,6,11,21,13,19,12}

7.1-2 当数组A[p..r]中的元素都相同时,PARTITION返回的q值是什么?修改PARTITION,使得当数组A[p..r]中所有元素的值都相同时,q=(p+r)/2.

当元素相同时,q=i+1=r-1+1=r.

修改后的函数q=(p+r)/2.

[cpp] view plain copy
  1. int Partition(int A[], int p, int r)  
  2. {  
  3.    int x = A[r],i=p-1;  
  4.    int flag = 1;  
  5.    for (int j = p;j< r-1;j++)  
  6.    {  
  7.        if (x >=A[i]&&flag>0)//x=A[i]时,flag大于0和小于0的数量约为一半,  
  8.        {  
  9.            i = i + 1;  
  10.            swap(A[i],A[j]);  
  11.        }  
  12.        if (x ==A[i])  
  13.        {  
  14.            flag=-flag;//这样就能让i++次数减半。  
  15.        }  
  16.    }  
  17.     swap(A[i + 1],A[r]);  
  18.    return i + 1  
  19. }  

7.1-3请简要证明:在规模为n的子数组上,PARTITION的时间复杂度为Θ(n)


除了函数内数个O(1),还有一个循环,其循环次数 p-(r-1)+1=p-r次,O(p-r)=O(n)


7.1-4  如何修改QUICKSORT,使得它能够以非递增序进行排序?

仅仅需要把  x >=A[i] 改为 x <=A[i]

7.2-1 利用带入法证明:正如7.2节开头提到的那样,递归式T(n)=T(n-1)+Θ(n)的解为T(n)=Θ(n^2)  令Θ(n)=cn (c常数)。

 假设T(n)在n-1上成立。  先证明T(n)=Ο(n^2)

T(n)<=c1(n-1)^2+cn<=c1n^2 <=> (c-2c1)n+c1<=0 <=> c-2c1<0 (c<2c1) n>=c1/(2c1-c) 当0<c<2c1时,有n>=n0=c1/(2c1-c)  对于足够大的n都成立。

再证明T(n)=Ω(n^2)  T(n)>=c2(n-1)^2+cn>=c2n^2  <=> (c-2c2)n+c2>=0 <=> c-2c2>0 (c>2c2>0) n>0 当c>2c2>0时,有n>0,对于足够大的n都成立。

 所以存在常数c1>c/2,c2<c/2时,存在n0=max{c1/(2c1-c),0},使得当n>=n0时,对于足够大的n都成立,T(n)=Θ(n^2)成立 

 7.2-2当数组A的所有元素都具有相同值时,QUICKSORT的时间复杂度是什么?  

 当数组A所有元素相同时,QUICKSORT中的划分时极为不平衡的,n-1:0的划分,T(n)=T(n-1)+Θ(n)解这个递归式T(n)=Θ(n^2) 

 7.2-3 证明:当数组A包含的元素不同,并且是按降序排列的时候,QUICKSORT的时间复杂度为Θ(n^2)

 按照降序排序时,在QUICKSORT中的划分时极为不平衡的,n-1:0的划分,所以其时间复杂度为T(n)=T(n-1)+Θ(n)解这个递归式  T(n)=T(n)=Θ(n^2)

 7.2-4 银行一半会按照交易时间来记录某一账户的交易情况。但是,很多人却喜欢收到银行对账单是按照支票号码的顺序来排列的。这是因为,人们通常  都是按照支票号码的顺序来开出支票的,而商人也通常都是根据支票编号的顺序兑付支票。这一问题时按照交易时间排序的序列转换成按支票号排序的  序列,它是指上是一个对几乎有序的输入序列进行排序的问题。请证明:在这个问题上,INSERTION-SORT的性能往往要优于QUICKSORT?

插入排序在基本有序的情况下,基本无需移动任何元素来插入,所以只有外层循环了n次,所以时间复杂度为O(n)

 快速排序在基本有序的情况下,在划分数组时,划分得非常不平衡,那么其时间复杂度是O(nlgn),而达到完全有序时,时间 复杂度达到O(n^2),</p><p>所以总之插入排序要优于快速排序。 

7.2-5 假设快速排序的每一层所做的划分的比例都是1-a:a,其中0<a<=1/2且是一个常数。是证明,在相应的递归树中,叶结点的最小深度大约是  -lgn/lga,最大深度大约是-lgn/lg(1-a)(无需考虑整数舍入问题) 

 0<=a<=1/2  =>  a<1-a 只有T(1)时,到达树底,设树高度为k,所以就有  最小深度(a^k)n=1=>k=-lgn/lga 最大深度(1-a)^kn=1 => k=-lgn/lg(1-a)

 7.2-6试证明:在一个随机输入数组上,对于任何常数0<a<=1/2,PARTITION产生比1-a:a更平衡的划分的概率约为1-2a      

 设随机数组有n个数,则有A0,A1...Aan...A(1-a)n...An。</p><p>设X个数被划分在左半部分,Y个数被划分在右半部分。

则X+Y=n  那么根据书上根据平衡的定义,X-Y差值越大,比例就越高,那么越不平衡,只有X-Y差值越小,越接近0,X约等于Y的时候  越平衡。

 分三种情况讨论:1)当X<a时,那么Y>1-a, |X-Y|>1-2a>0               

                              2)当X>1-a时,那么Y<a, |X-Y|>1-2a>0         

                              3)当a<X<1-a时,那么a<Y<1-a,0<|X-Y|<1-2a

 只有当|X-Y|距离小于一个数时,才可能X-Y差值趋向于0,划分的就越平衡。所以我们选择情况3的这种划分。  在an与(1-a)n之间取X的值,因为划分X落在区间[0,n]上是等可能性的,所以符合均匀分布,落在[an,(1-a)n}]上的任意一点  的概率也是等可能的,所以P{an≤x≤(1-a)n}=((1-a)n-an)/(n-0)=1-2a。得证! 

7.3-1 为什么我们分析随机化算法的期望运行时间,而不是其最坏运行时间呢?

 随机化算法不能改变最坏情况下得运行时间,但是能降低最坏情况发生的概率。

  7.3-2在RANDOMIZED-QUICKSORT的运行过程中,在最坏情况下,随机数生成器RANDOM被调用了多少次?在最好情况下呢? 

最好情况是均匀划分,其时间复杂度 T(n)=2T(n/2)+1 =>主定理case1得T(n)=Θ(n)   

最坏情况是分成不平衡的划分,其时间复杂度 T(n)=T(n-1)+T(0)+1 各式相加得=>T(n)=Θ(n)  

7.4-2 证明:在最好的情况下,快速排序的运行时间为Ω(nlgn)

最好情况就是均分的情况下,T(n)=2T(n/2)+Θ(n) 满足主定理case2=>T(n)=Θ(nlgn)=Ω(nlgn)

7.4-4 证明:RANDOMIZED-QUICKSORT期望运行时间是Ω(nlgn).

根据书中7.4.2知:随机化快速排序和普通快速排序就是主元选择上有所不同,其他都相同。所以我们可以用分析普通快排的方法分析随机快排,普通快排最好的情况是均分,其时间复杂度Ω(nlgn).,那么快速排序的时间复杂度至少最好情况下的Ω(nlgn)。所以随机化快排也是Ω(nlgn)。

7.4-5 当输入数据已经集合有序时,插入排序速度很快。在实际应用中,我们可以利用这一特点来提高快速排序的速度。当对一个长度小于k的子数组

调用快速排序时,让它不做任何排序就返回。当上层的快速排序调用返回后,对整个数组运行插入排序来完成排序过程。试证明,这一排序算法的期望

时间复杂度为O(nk+nlg(n/k)).分别从理论和实践的角度说明我们应该如何选择k?


7.4-5的具体程序实现如下:

[cpp] view plain copy
  1. #include <iostream>  
  2. using namespace std;  
  3. int PARTITION(int A[],int p,int r)  
  4. {  
  5.     int x=A[r];  
  6.     int i=p-1;  
  7.     for (int j=p;j<=r-1;j++)//O(n)这里应该包含第r-1个元素在循环里  
  8.     {  
  9.         if (A[j]<=x)  
  10.         {  
  11.             i++;  
  12.             swap(A[i],A[j]);  
  13.         }  
  14.     }  
  15.     swap(A[i+1],A[r]);  
  16.     return i+1;  
  17. }  
  18. void QUICKSORT(int A[],int p,int r,int k)  
  19. {  
  20.     if (p<r&&r-p>=k)//T(n)=2  
  21.     {  
  22.         int q=PARTITION(A,p,r);  
  23.         QUICKSORT(A,p,q-1,k);  
  24.         QUICKSORT(A,q+1,r,k);  
  25.     }  
  26. }  
  27. void INSERTION_SORT(int A[],int r)  
  28. {  
  29.     int key;  
  30.     for (int j=1;j<=r;j++)  
  31.     {  
  32.         key=A[j-1];  
  33.         int i=j-1;  
  34.         while (i>0&&A[i-1]<key)//a)插入排序时间复杂度O(n^2)对于长度为k的子列表都有O(k^2),则n/k个为(k^2)*n/k=O(nk)  
  35.         {  
  36.             A[i]=A[i-1];  
  37.             i=i-1;  
  38.         }  
  39.         A[i]=key;  
  40.     }  
  41. }  
  42. void main()  
  43. {  
  44.     int A[16]={1,5,10,8,9,4,6,2,7,3,14,20,35,48,25,34};  
  45.     QUICKSORT(A,0,15,4);//K=3  
  46.     for (int i=0;i<16;i++)  
  47.     {  
  48.         cout<<A[i]<<" ";  
  49.     }  
  50.     cout<<endl;  
  51.     INSERTION_SORT(A,16);  
  52.     for ( i=0;i<16;i++)  
  53.     {  
  54.         cout<<A[i]<<" ";  
  55.     }  
  56. }  

7.4-6 考虑对PARTITION过程做这样的修改,从数组A中随机选出三个元素,并用这三个元素的中位数(既这三个元素按大小排在中间的值)对数组进行

划分。求以a的函数形式表示的,最坏划分比例为a:(1-a)的近似概率,其中 0<a<1.

题目上说最坏划分比例是a:(1-a),那么由书中分析知 最坏划分比例是0:(n-1)或是(n-1):0 这才是最坏划分比例,所以
据我分析,题意应该是比a:(1-a)更坏的划分比例。还有就是因为是随机选取的3个元素并从中取中位数,那么从0到n-1上的每个
元素都可以做主元,所以取出的中位数是等可能的,符合均匀分布条件。
      设x为数组前半部分的元素个数,y为数组后半部分的元素个数。
当1<a<1/2时,a<1-a p(x<a)+p(x>1-a)+p(a<x<a-1)=1看7.2-6题已经给出答案。 x<a或者x>1-a时,划分情况比a:(1-a)更坏,
更糟糕的概率是p(x<a∪x>1-a)=p(x<a)+p(x>1-a)=1-p(a<x<1-a)=1-(1-2a)=2a
同上可知,当1/2<a<1时,a>1-a p(x>a)+p(x<1-a)+p(a<x<1-a)=1 ,x>a或者x<1-a时,划分情况比a:(1-a)更坏,更糟糕的概率
是p(x<1-a∪x>a)=p(x>a)+p(x<1-a)=1-p(a<x<1-a)=1-(2a-1)=2-2a

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章