距离上次更新已经 2037 天了,文章内容可能已经过时。

最近开始学习Coursera上普林斯顿的算法分析课程,后续会记录下学习过程,这次是第一周的内容。

课程主页:https://www.coursera.org/learn/analysis-of-algorithms

Exercise

1.14

Follow through the steps given for quicksort to solve the recurrence:

AN=1+2N1jNAj1 for N>0

解:两边乘以N可得

NAN=N+21jNAj1(N1)AN1=N1+21jN1Aj1

相减可得

NAN(N1)AN1=1+2AN1NAN(N+1)AN1=1

两边同除N(N+1)得到

ANN+1AN1N=1N(N+1)ANN+1AN1N=1N1N+1AN+1N+1=AN1+1N=A0+11

所以

AN=(A0+1)(N+1)1

1.15

Show that the average number of exchanges used during the first partitioning stage (before the pointers cross) is (N2)/6.

首先回顾源代码:

java
public class Quick
{
    private static int partition(Comparable[] a, int lo, int hi)
    {
        int i = lo, j = hi+1;
        while (true)
        {
            while (less(a[++i], a[lo])) if (i == hi) break;
            while (less(a[lo], a[--j])) if (j == lo) break;
            if (i >= j) break;
            exch(a, i, j);
    	}
        exch(a, lo, j);
        return j;
    }
    private static void sort(Comparable[] a, int lo, int hi)
    {
        if (hi <= lo) return;
        int j = partition(a, lo, hi);
        sort(a, lo, j-1);
        sort(a, j+1, hi);
    }
}

题目的意思是计算exch(a, lo, j)之前的平均交换次数。

不妨设元素为1,2,,N,假设主元为k,那么交换次数为a[1],,a[k1]中大于k的元素数量,考虑示性函数Xi,其中

Xi={1a[i]>k0a[i]<k

那么在主元为k的条件下,平均交换次数为

i=1k1E[Xi]=i=1k1NkN1=(k1)(Nk)N1=k(N+1)Nk2N1

因为k可以可以等概率的取1,2,,N中任意的数,所以平均交换次数为

1Nk=1Nk(N+1)Nk2N1=1N(N1)((N+1)N(N+1)2N2N(N+1)(2N+1)6)=1N1((N+1)22N(N+1)(2N+1)6)=1N1(N1)(N2)6=N26

1.17

If we change the first line in the quicksort implementation given in the lecture to call insertion sort when the subfile size is not greater than M then the total number of comparisons to sort N elements is described by the recurrence

CN={N+1+1N1jN(Cj1+CNj)N>M14N(N1)NM

Solve this recurrence.

对于N>M,递推式仍然为

CNN+1=CN1N+2N+1

递推可得

CNN+1=CMM+1+i=M+1N2i+1=M(M1)4(M+1)+i=M+2N+12i

所以对于N>M

CN=(N+1)(M(M1)4(M+1)+i=M+2N+12i)

1.18

CN=(N+1)(M(M1)4(M+1)+i=M+2N+12i)=(N+1)M(M1)4(M+1)+2(N+1)(ln(N+1)+γi=1M+11i)2NlnN+(M(M1)4(M+1)2i=1M+11i+2γ)N

所以

f(M)=M(M1)4(M+1)2i=1M+11i+2γ

不考虑常数项,作图可得

Code
当M= 8 时取最小值

代码如下:

python
import numpy as np
import matplotlib.pyplot as plt

M = np.arange(1, 100)
d1 = M * (M - 1) / (4 * (M + 1))
d2 = 2 * np.cumsum(1 / M)
f = d1 - d2

plt.plot(M, f)
plt.show()

print("当M=", M[np.argmin(f)], "时取最小值")

Problem

1

FN=N2+1+1N1kN(Fk1+FNk)FN=N2+1+2N1kNFk1NFN=N3+N+21kNFk1(N1)FN1=(N1)3+N1+21kN1Fk1

相减可得

NFN(N1)FN1=3N23N+1+1+2FN1NFN=(N+1)FN1+3N23N+2FNN+1=FN1N+3N23N+2N(N+1)FNN+1=FN1N+3N1N+1+2(1N1N+1)FNN+1=FN1N+3(12N+1)+2(1N1N+1)

累加可得

FNN+1=F01+3i=1N(12i+1)+2i=1N(1i1i+1)FNN+1=3N6i=1N1i+1+2(11N+1)FN=3N(N+1)6(N+1)i=1N1i+1+2N

2

Which of the following is a drawback to analyzing algorithms by proving O- upper bounds on the worst case?

  • Generally cannot be used to predict performance.
  • Likely to be too much detail in the analysis.
  • Generally cannot be used to compare algorithms.
  • Input model may be unrealistic.

显然答案如下:

Generally cannot be used to predict performance.

Generally cannot be used to compare algorithms.