课程主页:

https://cs170.org/

https://inst.eecs.berkeley.edu/~cs170/fa18/

课程视频:

https://www.bilibili.com/video/BV1wK411g7ck

这次回顾Hw2。

2.Counting inversions

  • 算法:Counting inversions
  • 输入:数组$A$,起点$\text{start}$,终点$\text{end}$
  • 输出:逆序数

算法流程:

  • 如果$\text{end}- \text{start}\le 0$,返回$0$
  • $l=\text{Counting inversions}(A, \text{start}, [n/2] -1)$
  • $r=\text{Counting inversions}(A, [n/2],\text{end})$
  • $B=[],i=0,j=0, c = 0$
    • while $(i \le [n/2] -1- \text{start})$ and $(j \le \text{end}- [n/2])$:
      • if $A[\text{start}+i] < A[[n/2] + j]$:
        • $B.\text{append}(A[\text{start}+i])$
        • $i=i+1$
      • else:
        • $B.\text{append}(A[[n/2] + j])$
        • $c=c+[n/2] -1 - i+1$
        • $j=j+1$
    • while $(i \le [n/2] -1- \text{start})$:
      • $B.\text{append}(A[\text{start}+i])$
      • $i=i+1$
    • while $(j \le \text{end}- [n/2])$:
      • $B.\text{append}(A[[n/2] + j])$
      • $j=j+1$
  • $A[l,\ldots, r] =B$
  • return $l+r+c$

递归关系:

3.Two sorted arrays

  • 算法:findIthOfTwoSortedArr
  • 输入:两个单调递增数组$A,B$,数组范围$l_A,r_A,l_B,r_B$,次序统计量$i(1\le i \le r_A -l_A+1+r_B-l_B+1)$
  • 输出:$A,B$中全体元素中第$i$大的值

算法流程:

  • if $r_B<l_B $:
    • return $A[l_A + i - 1]$
  • if $r_A < l_A$:
    • return $B[l_B + i-1]$
  • $j= i /2$
  • if $A[l_A + j -1] < B[l_B + j -1]$
    • return $\text{findIthOfTwoSortedArr}(A,B, l_A+j, r_A, l_B, r_B, i-j)$
  • else:
    • return $\text{findIthOfTwoSortedArr}(A,B, l_A, r_A, l_B +j , r_B, i-j)$

我们的目标是求中位数,假设

  • $n=\text{len}(A)$
  • $m=\text{len}(B)$

那么返回

正确性:

$A[l_A + j -1] < B[l_B + j -1]$,那么$A[l_A],\ldots, A[l_A + j -1]$必然不是第$i$大的元素,所以可以忽略,反之同理。

时间复杂度:

每次减少一半的搜索元素,所以时间复杂度为

实践练习:

4. 寻找两个正序数组的中位数

4.Majority Elements

(a)
  • 算法:Majority Elements
  • 输入:数组$A$,起点$\text{start}$,终点$\text{end}$
  • 输出:主元素

算法流程:

  • 如果$\text{end}- \text{start}\le 0$,返回$A[\text{start}]$
  • $l=\text{Majority Elements}(A, \text{start}, [n/2] -1)$
  • $r=\text{Majority Elements}(A, [n/2],\text{end})$
  • if $l==r$:
    • return $l$
  • else:
    • $c_1=0,c_2=0$
    • for $i=\text{start},\ldots,\text{end}$:
      • if $A[i]=l$:
        • $c_1=c_1+1$
      • else:
        • $c_2=c_2+1$
    • if $c_1\ge c_2$:
      • return $l$
    • else:
      • return $r$

正确性说明:

如果$d$是$A$的Majority Elements,那么$d$是$A[1,\ldots,[n/2] -1]$或$A[[n/2],\ldots,n]$的Majority Elements,这是因为如果上述结论不成立,那么$d$出现的次数$\le ([n/2]-1)/ 2+ (n-[n/2]+1)/2=n/2 $,这就与Majority Elements的定义矛盾。

在上述算法中,分别对$A$左右两段递归调用该算法,如果返回值相同,则显然是Majority Element;否则统计$l,r$的数量,最后返回数量较多的元素。

时间复杂度:

(b)

摩尔投票法:

  • 算法:Majority Elements
  • 输入:数组$A$,数组长度$n$
  • 输出:主元素

算法流程:

  • $a=A[1]$
  • $c=1$
  • for $i=2,\ldots, n$
    • if $A[i]!= a$:
      • $c=c-1$
      • if $c=0$:
        • $c=1$
        • $a=A[i]$
    • else:
      • $c=c+1$
  • return $a,c$

命题:

$f(n)$:对于长度为$n$,存在majority element的数组$A[1,\ldots, n]$,记$l=\text{number of majority element}$,那么上述算法的输出$c\ge l-(n-l)=2l-n > 0$且$a$为majority element。

证明:

$n=1$时结论显然成立。

假设$n=m-1$时结论成立,现在证明$n=m$时结论成立。

首先记majority element为$d$,且出现次数为$l$。

如果$m=2k$,那么$d$的出现次数大于$k$,所以在前$m-1=2k-1$个元素中出现次数大于$k-1$,即$d$也是$A[1,\ldots,2k-1]=A[1,\ldots,m-1]$的majority element。

如果$m=2k-1$,那么$d$的出现次数大于$k-1$,所以在前$m-1=2k-2$个元素中出现次数大于$k-2$。

  • 如果$d$的出现次数大于$k-1$,那么$d$也是$A[1,\ldots,2k-2]=A[1,\ldots,m-1]$的majority element。
  • 否则,$d$的出现次数为$k-1$。
    • 如果其余$k-1$个元素不全相同,那么每个元素出现的次数小于$k-1$,从而$d$依然是majority element。
    • 如果其余$k-1$个元素都相同,那么$A[m]=d$(majority element的定义),并且第$m$轮循环前,$c=1$,从而最后一轮循环必然返回$A[m]=d$,即此时结论已证(情形a)。

综上,除了情形a,$d$都是$A[1,\ldots,2k-2]=A[1,\ldots,m-1]$的majority element。

如果$A[m]=d$,那么由归纳假设可得在第$m$轮循环前,$c\ge 2(l-1)-(m-1), a=d$;在第$m$轮循环后,

如果$A[m]\neq d$,那么由归纳假设可得在第$m$轮循环前,$c\ge 2l-(m-1), a=d$;在第$m$轮循环后,

所以$T(n)$对$n=m$亦成立,从而原结论成立。

时间复杂度:

显然为$\Theta(n)$。

5.Merged Median

记$k$个排序数组为$A_i,i=1,\ldots,k$,记$A=A_1,\ldots, A_k$($A_i$拼接而成)。

  • 算法:Merged Median
  • 输入:数组$A$,数组长度$n$,参数$k,l$
  • 输出:排序后的数组$A$

算法流程:

  • $B=[A_1[[l/2]],\ldots, A_k[[l/2]]]$
  • $p=\text{DSelect}(B,k, [k/2])$
  • Partition $A$ around $p$,记$p$的索引为$j$,$p$之前元素构成的数组为$A^l$,$p$之后元素构成的数组为$A^r$
  • 如果$j= [n/2]$,返回$p$
  • 如果$j> [n/2]$,返回$\text{DSelect}(A^l, j -1, [n/2])$
  • 如果$j<[n/2]$,返回$\text{DSelect}(A^r, n-j, [n/2]-j)$

其中DSelect定义见如下链接:

https://doraemonzzz.com/2018/10/01/%E6%96%AF%E5%9D%A6%E7%A6%8F%E7%AE%97%E6%B3%95%E4%B8%93%E9%A1%B9%E8%AF%BE%E7%A8%8BCourse1%20week4%E5%86%85%E5%AE%B9%E5%9B%9E%E9%A1%BE/

6.Fourier Transform Basics

(a)
(b)
(c)
(d)

那么

对应的多项式为

7.Modular Fourier Transform

参考资料:

https://www.cs.drexel.edu/~jjohnson/2010-11/fall/cs567/lectures/threeprimes.pdf

(a)

那么

(b)
(c)

注意到

所以类比FFT可得

(d)

那么

对应的多项式为

实际结果应该为

8.Polynomial from roots

  • 算法:Polynomial from roots
  • 输入:次数$n$,零点$r_1,\ldots,r_n$
  • 输出:多项式的系数

算法流程:

  • 如果$n=1$,返回$[-r_1]$
  • $l=\text{Polynomial from roots}([n/2],[r_1,\ldots,r_{[n/2]}])$
  • $r=\text{Polynomial from roots}(n-[n/2],[r_{[n/2]+1},\ldots,r_{n}])$
  • $\text{res}= \text{FFT}_n^{-1}(\text{FFT}_n(l)\text{FFT}_n(r))$
  • return res

正确性显然,时间复杂度的递推如下:

利用递归树方法计算$T(n)$,在第$i$层的时间复杂度为

总时间复杂度为