二分搜索

来源:互联网 发布:黑格尔的哲学思想知乎 编辑:程序博客网 时间:2024/06/07 19:11

二分搜索

看到优化O(logn)时间复杂度问题, 一般用二分搜索

模板

int start = 0, end = array.size()-1, mid;while (start + 1 < end){    //该结束条件表示:当startend指针相邻(start + 1 == end),或者相交,或者错开 时终止,**一般是相邻时终止**。        mid = start + (end - start) / 2;        比较 A[mid] 与 target, 并且挪动 startend 指针}此时,startend相邻,分别判断startend 谁是我们需要寻找的节点。

经典难题

寻找两个数组中第k大的元素 (O(log(m+n)))

这个问题最暴力方法是分别将两个数组按照大小合并为一个数组,新数组的第k个就是答案。以下基于此优化
看到O(log)级别的时间复杂度首先想到用二分搜索解决,但是难点在于如何每次将问题模型减小一半?
- 二分减小问题规模
问题给定了两个数组,从直观上很容易想到分别将k/2的数据分给A、B两个数组,去比较它们k/2位置元素的大小。但如何通过比较大小的结果来减小问题的规模呢?
第k个元素不可能出现在k/2位置较小的那个数组里,反证法可以证明:
假设B[k/2]

    int findkth(vector<int> A, int startA, vector<int> B, int startB, int k) {        //考虑存在空数组        //并且startA与startB移动过程也可能移出所有元素,此时相当于A或B为空        if (startA >= A.size()) {            return B[startB + k - 1];        }        if (startB >= B.size()) {            return A[startA + k - 1];        }        if (k == 1) {            return A[startA] < B[startB] ? A[startA] : B[startB];        }        int A_key = startA + k/2 - 1 < A.size()                     ? A[startA + k/2 - 1]                    : INT_MAX;        int B_key = startB + k/2 - 1 < B.size()                     ? B[startB + k/2 - 1]                    : INT_MAX;        if (A_key < B_key) {            return findkth(A, startA + k/2, B, startB, k - k / 2);        }        else {            return findkth(A, startA, B, startB + k / 2, k - k / 2);        }    }
原创粉丝点击