zoukankan      html  css  js  c++  java
  • [LeetCode] 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)).

    分析:

    (1)median is the middle value in an ordered integer list. If the size of  the list is even, there is no middle value. So the median is the mean of the two middle value.

    Examples:

    • [2,3,4] , the median is 3

    • [2,3], the median is (2 + 3) / 2 = 2.5

    (2)logm+logn = log(mn)  <= log( (m + n)  ^ 2) =2 log(m + n)  ?= O(log(m + n))

    方法1:归并排序的最后一步,相当于把两个长度分别为m和n的子数组合并成有序的一个数组,合并后找出median,这样做的时间复杂度是O(m+n),需要额外空间O(m+n);

    class Solution {
    public:
        double findMedianSortedArrays(int A[], int m, int B[], int n) {
            int *C = new int[m+n];
            memcpy(C,A,sizeof(int)*m);
            memcpy(C+m,B,sizeof(int)*n);
            
            int med = (m+n)/2;
            sort(C,C+m+n);
            double median;
            if((m+n)%2)
            {
                median = (double)C[med];
                
            }
            else
                median = (double) (C[med]+C[(med-1)])/2; 
               
            delete []C;
            return median; 
        }
    };

    方法2:用两个指针分别指向两个数组的开头,哪个指针指向的数小则指针往前走一步,走k步之后(k=(m+n)/2),指针指向的值即是

    我们需要找的median,时间复杂度O(k),不需要额外的空间,即空间复杂度O(1);

    方法3:最好的时间复杂度O(log (m+n)),思路:Sorted Arrays -> Binary Search -> achieving logarithmic complexity,

    从排序数组就联想到二分查找的思路来考虑问题。

    参考博客:http://blog.csdn.net/yutianzuijin/article/details/11499917

    按寻找第k小数的思路,则k=(m+n)/2

    (1)首先假设数组A和B的元素个数都大于k/2,我们比较A[k/2-1]和B[k/2-1]两个元素,这两个元素分别表示A的第k/2小的元素和B的第k/2小的元素。这两个元素比较共有三种情况:>、<和=。如果A[k/2-1]<B[k/2-1],这表示A[0]到A[k/2-1]的元素都在A和B合并之后的前k小的元素中。换句话说,A[k/2-1]不可能大于两数组合并之后的第k小值,所以我们可以将其抛弃。

    证明也很简单,可以采用反证法。假设A[k/2-1]大于合并之后的第k小值,我们不妨假定其为第(k+1)小值。由于A[k/2-1]小于B[k/2-1],所以B[k/2-1]至少是第(k+2)小值。但实际上,在A中至多存在k/2-1个元素小于A[k/2-1],B中也至多存在k/2-1个元素小于A[k/2-1],所以小于A[k/2-1]的元素个数至多有k/2+ k/2-2,小于k,这与A[k/2-1]是第(k+1)的数矛盾。

    (2)当A[k/2-1]>B[k/2-1]时存在类似的结论。

    (3)当A[k/2-1]=B[k/2-1]时,我们已经找到了第k小的数,也即这个相等的元素,我们将其记为m。由于在A和B中分别有k/2-1个元素小于m,所以m即是第k小的数。(这里可能有人会有疑问,如果k为奇数,则m不是中位数。这里是进行了理想化考虑,在实际代码中略有不同,是先求k/2,然后利用k-k/2获得另一个数。)

    通过上面的分析,我们即可以采用递归的方式实现寻找第k小的数。此外我们还需要考虑几个边界条件:

    • 如果A或者B为空,则直接返回B[k-1]或者A[k-1];
    • 如果k为1,我们只需要返回A[0]和B[0]中的较小值;
    • 如果A[k/2-1]=B[k/2-1],返回其中一个;

    最终实现的代码为:

    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    double findKth(int a[], int m, int b[], int n, int k)  
    {  
        //always assume that m is equal or smaller than n  
        if (m > n)  
            return findKth(b, n, a, m, k);  
        if (m == 0)  
            return b[k - 1];  
        if (k == 1)  
            return min(a[0], b[0]);  
        //divide k into two parts  
        int pa = min(k / 2, m), pb = k - pa;  
        if (a[pa - 1] < b[pb - 1])  
            return findKth(a + pa, m - pa, b, n, k - pa);  // a的前半部分省略,寻找第k小的数变成寻找第k - pa小的数
        else if (a[pa - 1] > b[pb - 1])  
            return findKth(a, m, b + pb, n - pb, k - pb);  // b的前半部分省略,寻找第k小的数变成寻找第k - pb小的数
        else  
            return a[pa - 1];  
    }  
    
    class Solution  
    {  
    public:  
        double findMedianSortedArrays(int A[], int m, int B[], int n)  
        {  
            int total = m + n;  
            if (total & 0x1)  //表示m+n是奇数
                return findKth(A, m, B, n, total / 2 + 1);  
            else //m+n是偶数 
                return (findKth(A, m, B, n, total / 2)  
                + findKth(A, m, B, n, total / 2 + 1)) / 2;  
        }  
    };
  • 相关阅读:
    KMP算法代码实现记录
    冒泡,插入,希尔,快速,归并,桶排序,堆排序算法汇总实现
    回溯法个人理解记录(C#八皇后)
    C#创建初始化链表的方式(个人目前写出3种创建的方式)
    算法汇总代表性学习记录
    C#集合去重
    C#获取数组/字符串的k个字符的全部组合
    pl/sql简单执行记录个人学习记录
    oracle为什么尽量不要使用外键的最好理解
    PickerController 添加照片---iOS
  • 原文地址:https://www.cnblogs.com/Xylophone/p/3805164.html
Copyright © 2011-2022 走看看