zoukankan      html  css  js  c++  java
  • [LeetCode] 4. Median of Two Sorted Arrays 两个有序数组的中位数

    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)).

    You may assume nums1 and nums2 cannot be both empty.

    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

    求两个有序数组的中位数,限制了时间复杂度O(log (m+n))。

    如果m+n为奇数,则中位数为AB[(m+n)/2 + 1],偶数的话,中位数为(AB[(m+n)/2] + AB[(m+n)/2 + 1])/2。

    如果没有时间复杂度O(log(m+n))的要求,就可以对两个数组使用归并排序,再找到他们的中位数,直接遍历两个数组查找,用2个变量分别指向两个数组,每次取较小的一个,然后将其指针后移动,直到找到中位数,时间复杂度为O(m+n)。但不是题目想要考察的。

    解法:二分搜索Binary Search,T:O(log(m+n))。两个有序数组A(m), B(n),k = (m+n)/2,奇数时找k+1大的数,偶数是找第k大和第k+1大的数在除2。找第k((m+n)/2)大的数。先在A,B中分别找第k/2大的数,如果A[k/2-1]==B[k/2-1],那么这个数就是两个数组中第k大的数。如果A[k/2-1]<B[k/2-1], 那么说明A[0]到A[k/2-1]都不可能是第k大的数,所以需要舍弃这k/2,继续从A[k/2]到A[A.length-1]继续找。当然,因为这里舍弃了A[0]到A[k/2-1]这k/2个数,那么第k大也就变成了第k-k/2个大的数了。如果 A[k/2-1]>B[k/2-1],那么说明B[0]到B[k/2-1]都不可能是第k大的数,舍弃这k/2。如此迭代或者递归操作,如果有一个数组为空了,则返回另一个数组的第k大(剩下需要二分长度)的数。如果k==1,只需返回此时所以数中排第一小的数,就返回此时A,B中第一个元素小的那个。

    参考:爱做饭的小莹子

    Java:
    public class Solution {
        public double findMedianSortedArrays(int A[], int B[]) {
            int len = A.length + B.length;
            if (len % 2 == 1) {
                return findKth(A, 0, B, 0, len / 2 + 1);
            }
            return (
                findKth(A, 0, B, 0, len / 2) + findKth(A, 0, B, 0, len / 2 + 1)
            ) / 2.0;
        }
    
        public static int findKth(int[] A, int A_start,
                                  int[] B, int B_start,
                                  int k){    	
    		if (A_start >= A.length) {
    			return B[B_start + k - 1];
    		}
    		if (B_start >= B.length) {
    			return A[A_start + k - 1];
    		}
    
    		if (k == 1) {
    			return Math.min(A[A_start], B[B_start]);
    		}
    		
    		int A_key = A_start + k / 2 - 1 < A.length
    		            ? A[A_start + k / 2 - 1]
    		            : Integer.MAX_VALUE;
    		int B_key = B_start + k / 2 - 1 < B.length
    		            ? B[B_start + k / 2 - 1]
    		            : Integer.MAX_VALUE; 
    		
    		if (A_key < B_key) {
    			return findKth(A, A_start + k / 2, B, B_start, k - k / 2);
    		} else {
    			return findKth(A, A_start, B, B_start + k / 2, k - k / 2);
    		}
    	}
    }  

    Python:

    class Solution:
        # @return a float
        # @line20 must multiply 0.5 for return a float else it will return an int
        def getKth(self, A, B, k):
            lenA = len(A); lenB = len(B)
            if lenA > lenB: return self.getKth(B, A, k)
            if lenA == 0: return B[k - 1]
            if k == 1: return min(A[0], B[0])
            pa = min(k/2, lenA); pb = k - pa
            if A[pa - 1] <= B[pb - 1]:
                return self.getKth(A[pa:], B, pb)
            else:
                return self.getKth(A, B[pb:], pa)
        
        def findMedianSortedArrays(self, A, B):
            lenA = len(A); lenB = len(B)
            if (lenA + lenB) % 2 == 1: 
                return self.getKth(A, B, (lenA + lenB)/2 + 1)
            else:
                return (self.getKth(A, B, (lenA + lenB)/2) + self.getKth(A, B, (lenA + lenB)/2 + 1)) * 0.5 

    Python:

    class Solution(object):
        def findMedianSortedArrays(self, nums1, nums2):
            """
            :type nums1: List[int]
            :type nums2: List[int]
            :rtype: float
            """
            len1, len2 = len(nums1), len(nums2)
            if (len1 + len2) % 2 == 1: 
                return self.getKth(nums1, nums2, (len1 + len2)/2 + 1)
            else:
                return (self.getKth(nums1, nums2, (len1 + len2)/2) + 
                        self.getKth(nums1, nums2, (len1 + len2)/2 + 1)) * 0.5
    
        def getKth(self, A, B, k):
            m, n = len(A), len(B)
            if m > n:
                return self.getKth(B, A, k)
    
            left, right = 0, m    
            while left < right:
                mid = left + (right - left) / 2
                if 0 <= k - 1 - mid < n and A[mid] >= B[k - 1 - mid]:
                    right = mid
                else:
                    left = mid + 1
    
            Ai_minus_1 = A[left - 1] if left - 1 >= 0 else float("-inf")
            Bj = B[k - 1 - left] if k - 1 - left >= 0 else float("-inf")
    
            return max(Ai_minus_1, Bj)
    

    C++:

    class Solution {
    public:
        double findKth(vector<int>& A, vector<int>& B, int A_st, int B_st, int k) {
            // 边界情况,任一数列为空
            if (A_st >= A.size()) {
                return B[B_st + k - 1];
            }
            if (B_st >= B.size()) {
                return A[A_st + k - 1];
            }
            // k等于1时表示取最小值,直接返回min
            if (k == 1) return min(A[A_st], B[B_st]);
            int A_key = A_st + k / 2 - 1 >= A.size() ? INT_MAX : A[A_st + k / 2 - 1];
            int B_key = B_st + k / 2 - 1 >= B.size() ? INT_MAX : B[B_st + k / 2 - 1];
            if (A_key < B_key){
                return findKth(A, B, A_st + k / 2, B_st, k - k / 2);
            } else {
                return findKth(A, B, A_st, B_st + k / 2, k - k / 2);
            }
            
        }
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
            int sum = nums1.size() + nums2.size();
            double ret;
            
            if (sum & 1) {
                ret = findKth(nums1, nums2, 0, 0, sum / 2 + 1);
            } else {
                ret = ((findKth(nums1, nums2, 0, 0, sum / 2)) +
                        findKth(nums1, nums2, 0, 0, sum / 2 + 1)) / 2.0;
            }
            return ret;
        }
    };
    

       

    All LeetCode Questions List 题目汇总 

  • 相关阅读:
    Python环境搭建
    appium的android端的环境搭建(Window)
    Unittest中常用的十四种断言方法
    Leetcode-141(判断链表是否存在环)
    Leetcode-88(归并两个有序数组)
    Leetcode-680(回文字符串)
    Leetcode-345(反转字符串中的元音字符)
    Leetcode-633 (两数平方和)
    Leetcode-167(有序数组的 Two Sum)
    判断是否为小数
  • 原文地址:https://www.cnblogs.com/lightwindy/p/8491325.html
Copyright © 2011-2022 走看看