算法学习——递归实践

来源:互联网 发布:域名备案要钱吗 编辑:程序博客网 时间:2024/06/14 17:45

递归实践:求两个有序序列的中位数

完成日期:2017/9/26


    • 递归实践求两个有序序列的中位数
      • 实验内容
        • 实践题目
        • 问题描述
        • 算法描述
        • 算法时间及空间复杂度分析
        • 程序代码
        • 程序运行截图
        • 心得体会

实验内容

1. 实践题目

求两个有序序列的中位数

2. 问题描述

已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。
有序序列A0 ,A1 ,⋯,AN−1 的中位数指A(N−1)/2 的值,即第⌊(N+1)/2⌋个数(A0 为第1个数)。
要求时间复杂度为o(logN)

3. 算法描述

分别求出序列a和序列b的中位数a[mid1]和b[mid2],比较两个中位数的大小,会出现三种情况:
1). a[mid1] = b[mid2]:即a[mid1]为两个序列的中位数;
2). a[mid1] < b[mid2]:则中位数会出在a[mid1]和b[mid2]之间,在序列a
中删除a[mid1]之前的元素得到序列a1,在序列b中删除b[mid2]之后的元素得到序列b1;
3). a[mid1] > b[mid2]: 则中位数会出在b[mid2]和a[mid1]之间,在序列a
中删除a[mid1]之后的元素得到序列a1,在序列b中删除b[mid2]之前的元素得到序列b1;
在a1和b1中分别求出中位数,重复上述步骤1 2 3,如果得到两个序列都只剩一个元素,则两个元素中较小的那个就是所求。
注意:因为要求每次两个序列要舍弃的长度要相等,因此序列有奇数个元素和偶数个元素要分开讨论。

4. 算法时间及空间复杂度分析

因为每次求得两个序列的中位数之后,得到的两个子序列的长度都是上两个序列的一半,因为循环共执行log2N次,因此时间复杂度为o(logN)。
因为算法除了简单的变量以外,没有与N规模相关的辅助变量,因此空间复杂度为o(1)。

5. 程序代码

#include <iostream>using namespace std; void searchZ(int a[], int b[], int k){    int l1 =0, l2 = 0, r1 = k-1, r2 = k-1;    int mid1, mid2;    while (l1 <r1&&l2 <r2){        mid1 = (l1 + r1) / 2;        mid2 = (l2 + r2) / 2;        if ( a[mid1] == b[mid2]){            cout << a[mid1] << endl;            return;        }        else if (a[mid1] < b[mid2]){            if((l1 + r1) % 2 == 0){                l1 = mid1;                r2 = mid2;            }            else{                l1 = mid1 + 1;                r2 = mid2;            }        }        else{            if((l1 + r1) % 2 == 0){                r1 = mid1;                l2 = mid2;            }            else{                r1 = mid1;                l2 = mid2 + 1;            }        }       }    if (a[l1] < b[l2]){        cout << a[l1];    }    else{        cout << b[l2];    }    return;} int main() {    int k;    cin >> k;    int n[k+1];    int m[k+1];    for (int i = 0; i <k; i++){        cin >> n[i];    }    for (int j = 0; j < k; j++){        cin >> m[j];    }    searchZ(m, n, k);    return 0;}

6. 程序运行截图

这里写图片描述

7. 心得体会

看到题目所要求的时间复杂度为o(logn)时,结合之前所学的归并排序,知道如果要算法时间的数量级为logn的话,每循环一次之后数据的规模都要减半,因此首先需要思考如何在每一次循环之后n要变成n/2,也就是运用上mid。
然后算法的框架出来之后,一开始运行的时候出现了无限循环的情况,后来思考了一下,发现自己忽略两个序列每次都要舍弃的长度要相同,因此需要分奇偶讨论。
后来老师提出了一个不需要分奇偶讨论的方法,就是mid1 = (left1 + right1) /2, mid2 = (left2 + right2+1)/2,这样对奇数个元素时没有影响,但是又能保证在偶数个元素时,两个序列舍弃的长度相同,但是这种做法我在实施的时候,遇到了一个很严重的问题:

这里写图片描述

思考了很久只得出了一个解决方法= =,就是在最后每个序列只剩下2个元素的时候,对这四个元素进行排序得到中位数,这样对时间复杂度没有做什么贡献,但是会有些累赘。除了这个以外就没想到其他的方法了。

原创粉丝点击