码迷,mamicode.com
首页 > 编程语言 > 详细

leetcode | Median of Two Sorted Arrays 寻找2个有序数组中第k大的值

时间:2015-05-10 19:03:48      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:array   sorted   

问题 Median of Two Sorted Arrays

There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. 
The overall run time complexity should be O(log(m + n)).

分析

本题更经典通用的描述方式时:
给定2个有序数组,找出2个数组中所有元素中第k大的元素。

思路1

直观思路就是类似merge-sort,将2个数组merge成一个数组,即可得到第k大的值,但是时间复杂度O(m+n);

思路2

然后我们仅需要第k大的元素,不需要排序这个复杂的操作:可以定义一个计数器m,表示找到了第m大的元素;同时指针pa,pb分别指向数组A,B的第一个元素,使用merge-sort的方式,当A的当前元素小于B的当前元素时:pa++, m++,当*pb < *pa时,pb++, m++。最终当m等于k时,就得到了第k大的元素。时间复杂度O(k),但是当k接近于m+n时,复杂度还是O(m+n);

思路3

从题目中的要求O(log(m+n))可以联想到肯定要用到二分查找的思想

那么有没有更好的方案?我们可以考虑从k入手。如果我们每次能够删除一个一定处于第k大元素之前的元素,那么需要进行k次。但是如果我们每次都能删除一半呢?可以利用A,B有序的信息,类似二分查找,也是充分利用有序。
假设A 和B 的元素个数都大于k/2,我们将A 的第k/2 个元素(即A[k/2-1])和B 的第k/2个元素(即B[k/2-1])进行比较,有以下三种情况(为了简化这里先假设k 为偶数,所得到的结论对于k 是奇数也是成立的):
- A[k/2 - 1] == B[k/2 - 1];
- A[k/2 - 1] > B[k/2 - 1];
- A[k/2 - 1] < B[k/2 - 1];
如果A[k/2 - 1] < B[k/2 - 1] ,意味着 A[0] 到 A[k/2 - 1] 的元素一定小于 A+B 第k大的元素。因此可以放心的删除A数组中的这k/2个元素;
同理,A[k/2 - 1] > B[k/2 - 1];可以删除B数组中的k/2个元素;
当A[k/2 - 1] == B[k/2 - 1] 时,说明找到了第k大的元素,直接返回A[k/2 - 1] 或B[k/2 - 1]的值。

因此可以写一个递归实现,递归终止条件是什么呢?
- A或B为空时,直接返回A[k-1] 或 B[k-1]
- 当k = 1时,返回min(A[0], B[0]) //第1小表示第一个元素
- 当A[k/2 - 1] == B[k/2 - 1] 时,返回A[k/2 - 1] 或B[k/2 - 1]

C语言实现

    static int find_kth(int* A, int m,int* B, int n, int k);
    static int min(p, q) {return (p < q) ? p : q;}
    double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
        int m = nums1Size;
        int n = nums2Size;
        int total = m+n;
        int k = total/2;
        if(total & 0x01) {
            return find_kth(nums1, m, nums2, n, k+1); //奇数,返回唯一中间值
        } else {
            return (find_kth(nums1, m, nums2, n, k) + find_kth(nums1, m, nums2, n, k+1)) / 2.0; //偶数,返回中间2个的平均值
        }
    }
    //找到A,B组合中第k小的值: AB[k-1]
    int find_kth(int* A, int m,int* B, int n, int k) {
        //假设m都小于n
        if (m > n)
            return find_kth(B, n, A, m, k);
        if (m == 0)
            return B[k-1];
        if (k == 1) //终止条件
            return min(A[0], B[0]);

        int i_a = min(m, k/2);
        int i_b = k - i_a;

        if (A[i_a-1] < B[i_b-1])
            return find_kth(A+i_a, m-i_a, B, n, k-i_a);
        else if (A[i_a-1] > B[i_b-1])
            return find_kth(A, m, B+i_b, n-i_b, k-i_b);
        else
            return A[i_a-1];
    }

参考:https://github.com/soulmachine/leetcode

leetcode | Median of Two Sorted Arrays 寻找2个有序数组中第k大的值

标签:array   sorted   

原文地址:http://blog.csdn.net/quzhongxin/article/details/45622361

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!