zoukankan      html  css  js  c++  java
  • Leetcode 4 Median of Two Sorted Arrays


    4. Median of Two Sorted Arrays


    Total Accepted: 99662 Total Submissions: 523759

    Difficulty: Hard

    There are two sorted arrays nums1 and nums2 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)).

    Example 1:

    nums1 = [1, 3]

    nums2 = [2]

    The median is 2.0

    Example 2:

    nums1 = [1, 2]

    nums2 = [3, 4]

    The median is (2 + 3)/2 = 2.5


    方案0:合并两个数组为一个数组,排序,取第k个

    class Solution {
    public:
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2)
        {
            
            // Start typing your C/C++ solution below
            // DO NOT write int main() function
            int m = nums1.size();
            int n = nums2.size();
            vector<int>   v;   
    		v.insert(v.end(),   nums1.begin(),   nums1.end());   
    		v.insert(v.end(),   nums2.begin(),   nums2.end()); 
    		
            
            
            sort(v.begin(),v.end());
            
            double median=(double) ((n+m)%2? v[(n+m)/2]:(v[(n+m-1)/2]+v[(n+m)/2])/2.0);
            
            
            
            return median;
        }
    };




    方案1:假设两个数组总共有n个元素,用merge sort的思路排序,排序好的数组取出下标为k-1的元素就是我们需要的答案。
    这个方法比较容易想到,但是有没有更好的方法呢?


    方案2:可以用一个计数器,记录当前已经找到第m大的元素。同时我们使用两个指针pA和pB,分别指向A和B数组的第一个元素。使用类似于merge sort的原理,如果数组A当前元素小,那么pA++,同时m++。如果数组B当前元素小,那么pB++,同时m++。最终当m等于k的时候,就得到了我们的答案——O(k)时间,O(1)空间。


    但是,当k很接近于n的时候,这个方法还是很费时间的。当然,我们可以判断一下,如果k比n/2大的话,我们可以从最大的元素开始找。但是如果我们要找所有元素的中位数呢?时间还是O(n/2)=O(n)的。有没有更好的方案呢?


    我们可以考虑从k入手。如果我们每次都能够剔除一个一定在第k大元素之前的元素,那么我们需要进行k次。但是如果每次我们都剔除一半呢?所以用这种类似于二分的思想,我们可以这样考虑:

    Assume that the number of elements in A and B are both larger than k/2, and if we compare the k/2-th smallest element in A(i.e. A[k/2-1]) and the k-th smallest element in B(i.e. B[k/2 - 1]), there are three results:
    (Becasue k can be odd or even number, so we assume k is even number here for simplicy. The following is also true when k is an odd number.)
    A[k/2-1] = B[k/2-1]
    A[k/2-1] > B[k/2-1]
    A[k/2-1] < B[k/2-1]
    if A[k/2-1] < B[k/2-1], that means all the elements from A[0] to A[k/2-1](i.e. the k/2 smallest elements in A) are in the range of k smallest elements in the union of A and B. Or, in the other word, A[k/2 - 1] can never be larger than the k-th smalleset element in the union of A and B.

    Why?
    We can use a proof by contradiction. Since A[k/2 - 1] is larger than the k-th smallest element in the union of A and B, then we assume it is the (k+1)-th smallest one. Since it is smaller than B[k/2 - 1], then B[k/2 - 1] should be at least the (k+2)-th smallest one. So there are at most (k/2-1) elements smaller than A[k/2-1] in A, and at most (k/2 - 1) elements smaller than A[k/2-1] in B.So the total number is k/2+k/2-2, which, no matter when k is odd or even, is surly smaller than k(since A[k/2-1] is the (k+1)-th smallest element). So A[k/2-1] can never larger than the k-th smallest element in the union of A and B if A[k/2-1]<B[k/2-1];
    Since there is such an important conclusion, we can safely drop the first k/2 element in A, which are definitaly smaller than k-th element in the union of A and B. This is also true for the A[k/2-1] > B[k/2-1] condition, which we should drop the elements in B.
    When A[k/2-1] = B[k/2-1], then we have found the k-th smallest element, that is the equal element, we can call it m. There are each (k/2-1) numbers smaller than m in A and B, so m must be the k-th smallest number. So we can call a function recursively, when A[k/2-1] < B[k/2-1], we drop the elements in A, else we drop the elements in B.


    We should also consider the edge case, that is, when should we stop?
    1. When A or B is empty, we return B[k-1]( or A[k-1]), respectively;
    2. When k is 1(when A and B are both not empty), we return the smaller one of A[0] and B[0]
    3. When A[k/2-1] = B[k/2-1], we should return one of them

    In the code, we check if m is larger than n to garentee that the we always know the smaller array, for coding simplicy.


    中文翻译:

    该方法的核心是将原问题转变成一个寻找第k小数的问题(假设两个原序列升序排列),这样中位数实际上是第(m+n)/2小的数。所以只要解决了第k小数的问题,原问题也得以解决。

    首先假设数组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)的数矛盾。

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

    当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],返回其中一个;

    // leetcode4.cpp : 定义控制台应用程序的入口点。
    //
    
    
    #include "stdafx.h"
    
    #define min(x,y) (x>y?y:x)
    #define max(x,y) (x>y?x:y)
    
    double findKth(int a[],int m,int b[],int n,int k)
    {
    	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);
    	else if(a[pa -1]>a[pb-1])
    		return findKth(a,m,b+pb,n-pb,k-pb);
    	else
    		return a[pa -1];
    
    }
    
    double findMedianSortedArrays(int A[],int m,int B[],int n)
    {
    	int total = m +n;
    	if (total&0x1)
    		return findKth(A,m,B,n,total/2+1);
    	else
    		return (findKth(A,m,B,n,total/2)+findKth(A,m,B,n,total/2+1))/2;
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
    	int a[]={1,2,3};
    	int b[]={555,666,999};
    	int result = findMedianSortedArrays(a,3,b,3);
    	return 0;
    }
    
    



    python解决方案:基本上和c++比较类似

    def findMedianSortedArrays(self, A, B):
        l = len(A) + len(B)
        if l % 2 == 1:
            return self.kth(A, B, l // 2)
        else:
            return (self.kth(A, B, l // 2) + self.kth(A, B, l // 2 - 1)) / 2.defkth(self, a, b, k):ifnot a:
            return b[k]
        ifnot b:
            return a[k]
        ia, ib = len(a) // 2 , len(b) // 2
        ma, mb = a[ia], b[ib]
    
        # when k is bigger than the sum of a and b's median indices if ia + ib < k:
            # if a's median is bigger than b's, b's first half doesn't include kif ma > mb:
                return self.kth(a, b[ib + 1:], k - ib - 1)
            else:
                return self.kth(a[ia + 1:], b, k - ia - 1)
        # when k is smaller than the sum of a and b's indiceselse:
            # if a's median is bigger than b's, a's second half doesn't include kif ma > mb:
                return self.kth(a[:ia], b, k)
            else:
                return self.kth(a, b[:ib], k)


    参考文献:


    http://blog.csdn.net/zxzxy1988/article/details/8587244

    http://blog.csdn.net/yutianzuijin/article/details/11499917


    网上看到了一张leetcode 的难度和考试频率分析表,转过来给大家看看,出现频率为5的题目还是背诵并默写吧,哈哈!



           

    1Two Sum25arraysort

        setTwo Pointers

    2Add Two Numbers34linked listTwo Pointers

         Math

    3Longest Substring Without Repeating Characters32stringTwo Pointers

        hashtable 

    4Median of Two Sorted Arrays53arrayBinary Search

    5Longest Palindromic Substring42string 

    6ZigZag Conversion31string 

    7Reverse Integer23 Math

    8String to Integer (atoi)25stringMath

    9Palindrome Number22 Math

    10Regular Expression Matching53stringRecursion

         DP

    11Container With Most Water32arrayTwo Pointers

    12Integer to Roman34 Math

    13Roman to Integer24 Math

    14Longest Common Prefix21string 

    153Sum35arrayTwo Pointers

    163Sum Closest31arrayTwo Pointers

    17Letter Combinations of a Phone Number33stringDFS

    184Sum32array 

    19Remove Nth Node From End of List23linked listTwo Pointers

    20Valid Parentheses25stringStack

    21Merge Two Sorted Lists25linked listsort

         Two Pointers

         merge

    22Generate Parentheses34stringDFS

    23Merge k Sorted Lists34linked listsort

        heapTwo Pointers

         merge

    24Swap Nodes in Pairs24linked list 

    25Reverse Nodes in k-Group42linked listRecursion

         Two Pointers

    26Remove Duplicates from Sorted Array13arrayTwo Pointers

    27Remove Element14arrayTwo Pointers

    28Implement strStr()45stringTwo Pointers

         KMP

         rolling hash

    29Divide Two Integers43 Binary Search

         Math

    30Substring with Concatenation of All Words31stringTwo Pointers

    31Next Permutation52arraypermutation

    32Longest Valid Parentheses41stringDP

    33Search in Rotated Sorted Array43arrayBinary Search

    34Search for a Range43arrayBinary Search

    35Search Insert Position22array 

    36Valid Sudoku22array 

    37Sudoku Solver42arrayDFS

    38Count and Say22stringTwo Pointers

    39Combination Sum33arraycombination

    40Combination Sum II42arraycombination

    41First Missing Positive52arraysort

    42Trapping Rain Water42arrayTwo Pointers

         Stack

    43Multiply Strings43stringTwo Pointers

         Math

    44Wildcard Matching53stringRecursion

         DP

         greedy

    45Jump Game II42array 

    46Permutations34arraypermutation

    47Permutations II42arraypermutation

    48Rotate Image42array 

    49Anagrams34string 

        hashtable 

    50Pow(x, n)35 Binary Search

         Math

    51N-Queens43arrayDFS

    52N-Queens II43arrayDFS

    53Maximum Subarray33arrayDP

    54Spiral Matrix42array 

    55Jump Game32array 

    56Merge Intervals45arraysort

        linked listmerge

        red-black tree 

    57Insert Interval45arraysort

        linked listmerge

        red-black tree 

    58Length of Last Word11string 

    59Spiral Matrix II32array 

    60Permutation Sequence51 permutation

         Math

    61Rotate List32linked listTwo Pointers

    62Unique Paths23arrayDP

    63Unique Paths II33arrayDP

    64Minimum Path Sum33arrayDP

    65Valid Number25stringMath

    66Plus One12arrayMath

    67Add Binary24stringTwo Pointers

         Math

    68Text Justification42string 

    69Sqrt(x)44 Binary Search

    70Climbing Stairs25 DP

    71Simplify Path31stringStack

    72Edit Distance43stringDP

    73Set Matrix Zeroes35array 

    74Search a 2D Matrix33arrayBinary Search

    75Sort Colors42arraysort

         Two Pointers

    76Minimum Window Substring42stringTwo Pointers

    77Combinations34 combination

    78Subsets34arrayRecursion

         combination

    79Word Search34arrayDFS

    80Remove Duplicates from Sorted Array II22arrayTwo Pointers

    81Search in Rotated Sorted Array II53arrayBinary Search

    82Remove Duplicates from Sorted List II33linked listRecursion

         Two Pointers

    83Remove Duplicates from Sorted List13linked list 

    84Largest Rectangle in Histogram52arrayStack

    85Maximal Rectangle51arrayDP

         Stack

    86Partition List33linked listTwo Pointers

    87Scramble String52stringRecursion

         DP

    88Merge Sorted Array25arrayTwo Pointers

         merge

    89Gray Code42 combination

    90Subsets II42arrayRecursion

         combination

    91Decode Ways34stringRecursion

         DP

    92Reverse Linked List II32linked listTwo Pointers

    93Restore IP Addresses33stringDFS

    94Binary Tree Inorder Traversal43treeRecursion

        hashtablemorris

         Stack

    95Unique Binary Search Trees II41treeDP

         DFS

    96Unique Binary Search Trees31treeDP

    97Interleaving String52stringRecursion

         DP

    98Validate Binary Search Tree35treeDFS

    99Recover Binary Search Tree42treeDFS

    100Same Tree11treeDFS

    101Symmetric Tree12treeDFS

    102Binary Tree Level Order Traversal34treeBFS

    103Binary Tree Zigzag Level Order Traversal43queueBFS

        treeStack

    104Maximum Depth of Binary Tree11treeDFS

    105Construct Binary Tree from Preorder and Inorder Tr33arrayDFS

        tree 

    106Construct Binary Tree from Inorder and Postorder T33arrayDFS

        tree 

    107Binary Tree Level Order Traversal II31treeBFS

    108Convert Sorted Array to Binary Search Tree23treeDFS

    109Convert Sorted List to Binary Search Tree43linked listRecursion

         Two Pointers

    110Balanced Binary Tree12treeDFS

    111Minimum Depth of Binary Tree11treeDFS

    112Path Sum13treeDFS

    113Path Sum II22treeDFS

    114Flatten Binary Tree to Linked List33treeRecursion

         Stack

    115Distinct Subsequences42stringDP

    116Populating Next Right Pointers in Each Node33treeDFS

    117Populating Next Right Pointers in Each Node II42treeDFS

    118Pascal's Triangle21array 

    119Pascal's Triangle II21array 

    120Triangle31arrayDP

    121Best Time to Buy and Sell Stock21arrayDP

    122Best Time to Buy and Sell Stock II31arraygreedy

    123Best Time to Buy and Sell Stock III41arrayDP

    124Binary Tree Maximum Path Sum42treeDFS

    125Valid Palindrome25stringTwo Pointers

    126Word Ladder II11  

    127Word Ladder35graphBFS

         shortest path

    128Longest Consecutive Sequence43array 

    129Sum Root to Leaf Numbers24treeDFS

    130Surrounded Regions43arrayBFS

         DFS

    131Palindrome Partitioning34stringDFS

    132Palindrome Partitioning II43stringDP

  • 相关阅读:
    面向对象
    面向对象
    面向对象
    面向对象
    面向对象
    面向对象
    面向对象
    面向对象
    3.1
    面向对象
  • 原文地址:https://www.cnblogs.com/wangyaning/p/7853901.html
Copyright © 2011-2022 走看看