Leetcode4: Median of Two Sorted Arrays (求已排序两个数组的中间值)

来源:互联网 发布:淘宝卖什么利润最高 编辑:程序博客网 时间:2024/06/06 07:20

最开始的想法是利用归并排序的归并merge函数将数组先完全排序,然后根据奇偶个数来决定中间值的大小,思路清晰,代码简单,如下:
<pre name="code" class="java">public class Solution {    public double findMedianSortedArrays(int A[], int B[]) {        int m = A.length;        int n = B.length;        int[] temp = new int[m+n];        int idx_a = 0;        int idx_b = 0;        int idx = 0;        while (idx_a < m && idx_b < n) {            if (A[idx_a] < B[idx_b]) {                temp[idx++] = A[idx_a++];            } else {                temp[idx++] = B[idx_b++];            }        }                while (idx_a < m) {            temp[idx++] = A[idx_a++];        }                 while (idx_b < n) {            temp[idx++] = B[idx_b++];        }                int medium = (m+n)>>1;        return (double) (m+n) % 2 == 0 ? (temp[medium] + temp[medium - 1])/2.0 : temp[medium];    }}


编译能够通过,但是好像不符合题目对时间复杂度的要求,该算法时间复杂度为O(n+m)。
在网上看到一种符合的算法,利用类似二分法的思想,先求合并集合A和B的第K大的元素,然后利用该小函数来求解中间值的问题:
对已排好序的两个数组,查找第k大元素,只需要每次比较每个数组前k/2个元素的大小,就可以排除k/2个干扰元素,从排除后的元素开始,继续寻找第k-l大的元素,l为已经被排除的元素个数,利用递归调用,直到找到第K大元素为止;关键是考虑递归结束的边界条件,和每次排除元素后调用函数传入参数的值,下面是代码:
<pre name="code" class="java">import java.util.*;public class Solution {    public double findMedianSortedArrays(int A[], int B[]) {        int m = A.length;        int n = B.length;        int total = m + n;        int k = (total+1) / 2;//第k大元素在数组中序列号为k-1,很关键        return total % 2 == 0 ? (find_kth_elm(A, m, B, n, k) + find_kth_elm(A, m, B, n, k+1))/2.0 :                                find_kth_elm(A, m, B, n, k);    }        /**     * 对已排序的两个数组查找第k大的元素     */    public int find_kth_elm(int a[], int m, int b[], int n, int k) {    //we always assume that m equal or less than n    if (m > n) {        return find_kth_elm(b, n, a, m, k);    }        //递归结束的边界条件    if (m == 0) {        return b[k-1];    }         if (k == 1) {        return a[0] < b[0] ? a[0] : b[0];    }        //每次搜索,将k/2个元素排除,递归寻找目标元素    int ma = (k/2 < m ? k/2 : m);    int nb = k - ma;    if (a[ma-1] > b[nb-1]) {        //则此时b[0:nb-1]必然是小于第k大的值,可以删除,从nb以后的元素中搜索,目标是A和B集合中第k-nb大的元素        return find_kth_elm(a, m, Arrays.copyOfRange(b, nb, n), n-nb, k-nb);    } else if (a[ma-1] < b[nb-1]) {        //则此时a[0:ma-1]必然是小于第k大的值,可以删除,从nb以后的元素中搜索,目标是A和B集合中第k-nb大的元素        return find_kth_elm(Arrays.copyOfRange(a, ma, m), m-ma, b, n, k-ma);    } else {        //a[ma-1]=b[nb-1],则此时第K大元素必然是该相等元素        return a[ma-1];    }        }}





0 0
原创粉丝点击