二分递归:Max2

471 阅读1分钟

数据结构(上)01E-8 二分递归:Max2

数据结构(上)01E-8 二分递归:Max2

Max2: 迭代1

在给定的数组区间 A[lo,hi)A[lo,hi) 中找出最大的两个元素 A[x1]A[x_1]A[x2]A[x_2]。元素比较的次数,要求尽可能得少。

AA中包含的元素是A[lo]A[lo]...A[lo+1]A[lo+1]...A[hi1]A[hi-1]

截屏2021-05-04 14.00.33.png

void max2(int A[], int lo, int hi, int & x1, int & x2){ // 1 < n = hi - lo
    for (x1 = lo, int i = lo + 1; i < hi; i ++) //扫描A[lo,hi), 找出A[x1]
        if (A[x1] < A[i]) x1 = i; // hi - lo - 1 = n - 1
    for (x2 = lo, int i = lo + 1; i < x1; i ++) //扫描A[lo, x1)
        if (A[x2] < A[i]) x2 = i; // x1 - lo - 1
    for (int i = x1 + 1; i < hi; i++) //再扫描A(x1, hi),找出A[x2] 
        if (A[x2] < A[i]) x2 = i; // hi - x1 - 1 
}

比较次数是: n1+(n2)=2n3n - 1 + (n - 2) = 2n - 3

Max2: 迭代2

截屏2021-05-04 14.11.12.png

void max2(int A[], int lo, int hi, int & x1, int & x2){ // 1 < n = hi - lo
    if (A[x1 = lo] < A[x2 = lo + 1]) swap(x1, x2);
    for (int i = lo + 2; i < hi; i++)
        if (A[x2] < A[i])
            if (A[x1] < A[x2 = i])
                swap(x1, x2)
     \\ else continue;
}

首先确认x1x1x2x2是扫描范围内的最大者和次大者。然后利用循环,从第三个元素开始逐一递增,第一步和x2x2作比较,只有当它大于x2x2时,才将x2x2更新为ii。第二步与x1x1作比较,如果大于x1x1,则交换位置。从而实现当前最大元素和次大元素的更新。

最好的情况是循环中是实行一次比较 1+(n2)×1=n11 + (n-2)\times 1 = n - 1

最坏的情况是实行两次比较 1+(n2)×2=2n31 + (n-2) \times 2 = 2n - 3

递归 + 分治

截屏2021-05-04 14.21.30.png

这里我们递归求解两个子问题:分别求出左侧的最大元素和次大元素,以及右侧的最大元素和次大元素。全局的最大元是max(x1L,x1R)\max(x1L, x1R),有两种情况,左侧胜出和右侧胜出。

先考虑左侧胜出。那么全局最大元素是max(x2L,x1R)\max(x2L, x1R)

void max2(int A[], int lo, int hi, int & x1, int & x2){
    if (lo + 2 == hi) {; return;} // T(2) = 1
    if (lo + 3 == hi) {; return;} // T(3) <= 3
    int mi = (lo + hi) / 2; //divide
    int x1L, x2L; max2(A, lo, mi, x1L, x2L);
    int x1R, x2R; max2(A, mi, hi, x1R, x2R);
    if (A[x1L] > A[x1R]){ // 对子区间的最大值进行比较(左图)
        x1 = x1L; // 第一层比较
        x2 = (A[x2L] > A[x1R]) ? x2L : x1R; // 第二层比较
    }
    else{
        x1 = x1R; 
        x2 = (A[x1L] > A[x2R]) ? x1L : x2R;
    } // 1 + 1 = 2
} // T(n) = 2*T(n/2) + 2 <= 5n / 3 -2 实现下降

首先递归树的叶子节点都在同一层,然后整个算法的复杂度是从叶子向根节点这样综合上去的,因此既然层数一定,唯一影响复杂度的就是叶子节点所代表的递归基的复杂度。递归基有两种T(3)和T(2),这两种都是不可再分的。前者复杂度为3,后者复杂度为2,因此最好的情况是递归树的叶子节点都是T(2),最差的情况是叶子节点都是T(3)。[ref 评论区]

下界:2ln(n/2)+111+n/2=3n/222^{ln(n/2)+1}-1-1+n/2=3n/2-2

上界:2ln(n/3)+111+(n/3)3=5n/322^{ln(n/3)+1}-1-1+(n/3)*3=5n/3-2