选择算法时间复杂度分析

选择算法

算法导论选择算法

期望时间为线性时间的选择算法

算法思想:设数组长度为n,要求数组中第i大的数字,在待选择的数组中选择一个数x,使用Partition函数(快排中的)进行划分,假设划分为两部分:
{ A [ 1 ] , A [ 2 ] , . . . , A [ k − 1 ] } , { A [ k + 1 ] , A [ k + 2 ] , . . . , A [ n ] } \left\{ {A[1], A[2],...,A[k-1]} \right\}, \left\{ {A[k+1], A[k+2],...,A[n]} \right\} {A[1],A[2],...,A[k1]},{A[k+1],A[k+2],...,A[n]}
现在,A[1 ~ (k-1)]都是小于A[k]的数字,A[(k+1) ~ n]都是大于A[k]的数字。对比 k 和 i 的大小,分为三种情况:

  • k = i: A[k]即是要找的数字,返回A[k]。
  • k < i: 要找的数字在高区,在高区递归调用Select。
  • k > i: 要找的数字在低区,在低区递归调用Select。

代码:

#include <bits/stdc++.h>

using namespace std;

int Partition(vector<int>& A, int q, int r) {
    int& x = A[q], i = q + 1;
    for (int j = q + 1; j <= r; j++) {
        if (A[j] < x) {
            swap(A[i], A[j]);
            i++;
        }
    }
    swap(A[i-1], x);
    return i-1;
}

int Select(vector<int>& A, int q, int r, int target) {
    if (q < 0 || r >= A.size()) return -1;
    int i = Partition(A, q, r);
    if (i == target) return A[i];
    else if (i > target) return Select (A, q, i-1, target);
    else return Select(A, i+1, r, target);
}

int main() {
    vector<int> A = {5,1,2,10,7,9};
    cout << Select(A, 0, A.size()-1, 5) << endl;
}

复杂度分析:

  • 最好情况下,第一次划分即得到目标值,此时的复杂度是 T ( n ) = Θ ( n ) T(n)=\Theta(n) T(n)=Θ(n)
  • 最好情况下,每一次划分都将数组划分为两部分:0个元素和n-1个元素,而目标值存在n-1个元素的部分里。递归式为 T ( n ) = T ( n − 1 ) + Θ ( n ) T(n) = T(n-1) + \Theta(n) T(n)=T(n1)+Θ(n),现在证明 T ( n ) = Θ ( n 2 ) T(n) = \Theta(n^2) T(n)=Θ(n2)
    T ( n ) = T ( n − 1 ) + Θ ( n ) = c ( n − 1 ) 2 + Θ ( n ) = c n 2 − 2 c n + c + Θ ( n ) = c n 2 − [ c ( 2 n − 1 ) − Θ ( n ) ] ≤ c n 2 \begin{aligned} T(n) &= T(n-1) + \Theta(n) \\ &= c(n-1)^2 + \Theta(n) \\ &= cn^2 - 2cn + c + \Theta(n) \\ &= cn^2 - [c(2n-1) - \Theta(n)] \\ & \le cn^2 \end{aligned} T(n)=T(n1)+Θ(n)=c(n1)2+Θ(n)=cn22cn+c+Θ(n)=cn2[c(2n1)Θ(n)]cn2
  • 时间复杂度的期望值:

设指示器随机变量(indicator):
x k = { 1 , if k : n-k-1 split , 0 , otherwise x_k = \begin{cases} 1, & \text{if k : n-k-1 split}, \\ 0, & \text{otherwise} \end{cases} xk={1,0,if k : n-k-1 split,otherwise
由于每次的k是独立的,因此 E ( x k ) = 1 n E(x_k) = \frac{1}{n} E(xk)=n1
将划分的所有情况的时间复杂度公式写出,则是:
T ( n ) ≤ { T ( m a x { 0 , n − 2 } ) + Θ ( n ) , if 0, n-1 split T ( m a x { 1 , n − 2 } ) + Θ ( n ) , if 1, n-2 split . . . T ( m a x { k , n − k − 1 } ) + Θ ( n ) , if k, n-k-1 split . . . T ( m a x { n − 1 , 0 } ) + Θ ( n ) , if n-1, 0 split = ∑ k = 0 n − 1 x k ( T ( m a x { k , n − k − 1 } ) + Θ ( n ) ) \begin{aligned} T(n) &\le \begin{cases} T(max\left\{0, n-2\right\}) + \Theta(n), &\text{if 0, n-1 split}\\ T(max\left\{1, n-2\right\}) + \Theta(n), &\text{if 1, n-2 split}\\ ... \\ T(max\left\{k, n-k-1\right\}) + \Theta(n), &\text{if k, n-k-1 split}\\ ... \\ T(max\left\{n-1, 0\right\}) + \Theta(n), &\text{if n-1, 0 split} \\ \end{cases} \\ &= \sum_{k=0}^{n-1}x_k(T(max\left\{k, n-k-1\right\}) + \Theta(n)) \end{aligned} T(n) T(max{0,n2})+Θ(n),T(max{1,n2})+Θ(n),...T(max{k,nk1})+Θ(n),...T(max{n1,0})+Θ(n),if 0, n-1 splitif 1, n-2 splitif k, n-k-1 splitif n-1, 0 split=k=0n1xk(T(max{k,nk1})+Θ(n))
故有:
E ( T ( n ) ) = E ( ∑ k = 0 n − 1 x k ( T ( m a x { k , n − k − 1 } ) + Θ ( n ) ) ) E(T(n)) = E(\sum_{k=0}^{n-1}x_k(T(max\left\{k, n-k-1\right\}) + \Theta(n))) E(T(n))=E(k=0n1xk(T(max{k,nk1})+Θ(n)))
由期望的线性性质可得:
E ( T ( n ) ) = E ( ∑ k = 0 n − 1 x k ( T ( m a x { k , n − k − 1 } ) + Θ ( n ) ) ) = E ( x k ) ∗ E ( ∑ k = 0 n − 1 ( T ( m a x { k , n − k − 1 } ) ) ) + E ( ∑ k = 0 n − 1 Θ ( n ) ) = 1 n E ( ∑ k = 0 n − 1 ( T ( m a x { k , n − k − 1 } ) ) ) + Θ ( n ) \begin{aligned} E(T(n)) &= E(\sum_{k=0}^{n-1}x_k(T(max\left\{k, n-k-1\right\}) + \Theta(n))) \\ &= E(x_k) * E(\sum_{k=0}^{n-1}(T(max\left\{k, n-k-1\right\}))) + E(\sum_{k=0}^{n-1}\Theta(n)) \\ &= \frac{1}{n}E(\sum_{k=0}^{n-1}(T(max\left\{k, n-k-1\right\}))) + \Theta(n) \end{aligned} E(T(n))=E(k=0n1xk(T(max{k,nk1})+Θ(n)))=E(xk)E(k=0n1(T(max{k,nk1})))+E(k=0n1Θ(n))=n1E(k=0n1(T(max{k,nk1})))+Θ(n)
由于 k k k n − k − 1 n-k-1 nk1相加固定为 n − 1 n-1 n1,因此
∑ k = 0 n − 1 T ( m a x { k , n − k − 1 } ) ) ≤ 2 ∗ ∑ k = ⌊ n 2 ⌋ n − 1 T ( k ) \sum_{k=0}^{n-1}T(max\left\{k, n-k-1\right\})) \le 2 * \sum_{k=\lfloor{\frac{n}{2}}\rfloor}^{n-1}T(k) k=0n1T(max{k,nk1}))2k=2nn1T(k)
当n为偶数时为等号。
故上式化简为:
E ( T ( n ) ) = 1 n E ( ∑ k = 0 n − 1 T ( m a x { k , n − k − 1 } ) ) + Θ ( n ) ≤ 2 n E ( ∑ k = ⌊ n 2 ⌋ n − 1 T ( k ) ) + Θ ( n ) = 2 n ∑ k = ⌊ n 2 ⌋ n − 1 E ( T ( k ) ) + Θ ( n ) \begin{aligned} E(T(n)) &= \frac{1}{n}E(\sum_{k=0}^{n-1}T(max\left\{k, n-k-1\right\})) + \Theta(n) \\ &\le \frac{2}{n}E(\sum_{k=\lfloor{\frac{n}{2}}\rfloor}^{n-1}T(k)) + \Theta(n) \\ &= \frac{2}{n}\sum_{k=\lfloor{\frac{n}{2}}\rfloor}^{n-1}E(T(k)) + \Theta(n) \end{aligned} E(T(n))=n1E(k=0n1T(max{k,nk1}))+Θ(n)n2E(k=2nn1T(k))+Θ(n)=n2k=2nn1E(T(k))+Θ(n)
现在假设其上界为线性,即 E ( T ( n ) ) ≤ c n E(T(n)) \le cn E(T(n))cn,通过代入法进行推导:
E ( T ( n ) ) ≤ 2 n ∑ k = ⌊ n 2 ⌋ n − 1 E ( T ( k ) ) + Θ ( n ) ≤ 2 n ∑ k = ⌊ n 2 ⌋ n − 1 c k + Θ ( n ) ≤ 2 n ∗ 3 8 c n 2 + Θ ( n ) = c n − ( 1 4 c n − Θ ( n ) ) ≤ c n \begin{aligned} E(T(n)) &\le \frac{2}{n}\sum_{k=\lfloor{\frac{n}{2}}\rfloor}^{n-1}E(T(k)) + \Theta(n) \\ & \le \frac{2}{n}\sum_{k=\lfloor{\frac{n}{2}}\rfloor}^{n-1}ck + \Theta(n) \\ & \le \frac{2}{n} * \frac{3}{8}cn^2 + \Theta(n) \\ & = cn - (\frac{1}{4}cn - \Theta(n)) \\ & \le cn \end{aligned} E(T(n))n2k=2nn1E(T(k))+Θ(n)n2k=2nn1ck+Θ(n)n283cn2+Θ(n)=cn(41cnΘ(n))cn
因为 Θ ( n ) \Theta(n) Θ(n)在特定规模下是确定的,因此对于每种规模都能取到 c c c值使得上式成立。故该选择算法的期望时间复杂度为 Θ ( n ) \Theta(n) Θ(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值