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

原文地址:https://www.cnblogs.com/wuyida/p/6301269.html