LeetCode 4. Median of Two Sorted Arrays (Hard)

题目

 
Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.

The overall run time complexity should be O(log (m+n)).

Example 1:

Input: nums1 = [1,3], nums2 = [2]
Output: 2.00000
Explanation: merged array = [1,2,3] and median is 2.

Example 2:

Input: nums1 = [1,2], nums2 = [3,4]
Output: 2.50000
Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.

Constraints:

nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106

 

思路:

解法(Java):

由于题目中限定了时间复杂度为O(log(m+n)),所以采用二分法。

首先考虑取两个数组所有元素中第k大的数,k从1开始。

 

A [ 1 ],A [ 2 ],A [ 3 ],A [ k / 2] ... ,

B[ 1 ],B [ 2 ],B [ 3 ],B[ k / 2] ... ,

如果 A [ k / 2 ] < B [ k / 2 ] ,那么 A [ 1 ],A [ 2 ],A [ 3 ],A [ k / 2] 都不可能是第 k 小的数字。

 
推导:A 数组中比 A [ k / 2 ] 小的数有 k / 2 - 1 个,B 数组中,B [ k / 2 ] 比 A [ k / 2 ] 大,假设 B [ k / 2 ] 前边的数字都比 A [ k / 2 ] 小,也只有 k / 2 - 1 个,所以比 A [ k / 2 ] 小的数字最多有 (k / 2 - 1) + (k / 2 - 1) = k - 2 个,所以 A [ k / 2 ] 最多是第 k - 1 小的数。而比 A [ k / 2 ] 小的数更不可能是第 k 小的数了,所以可以把它们排除。

 
递归边界情况:

假设数组nums1长度始终小于数组nums2

nums1长度为0,直接返回nums2中第k大的值。

当k = 1,取nums1和nums2两者的最小值。

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m = nums1.length, n = nums2.length;
        //求中位数,若总数为奇数,则中位数为中间元素,
        //若为偶数,则为中间两个元素的平均数
        //这里统一起来,
        //奇数时,left和right其实指的是同一个数
        //偶数时,left代表中位数左边那个数,right代表右边那个数
        //left和right的值代表数是第几大(从1开始)
        int left = (m+n+1)/2, right = (m+n+2)/2;
        
        double res = getKth(nums1, 0, m-1, nums2, 0, n-1, left);
        //两个数组元素总是是奇数的情况
        if(left == right) return res;
        //偶数情况
        res = (res + getKth(nums1, 0, m-1, nums2, 0, n-1, right))/2;
        return res;
    }
    
    private double getKth(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k){
        int len1 = end1 - start1 + 1;
        int len2 = end2 - start2 + 1;
        // 使nums1始终是长度小的那个数组
        if(len1 > len2) return getKth(nums2, start2, end2, nums1, start1, end1, k);
        
        if(len1 == 0) return nums2[start2 + k -1];
        if(k == 1) return Math.min(nums1[start1], nums2[start2]);
        
        // 当nums1长度小于k/2,为防止数组下标越界,则i取最后一个数下标
        int i = start1 + Math.min(len1, k/2) - 1;
        // 因为nums2始终比nums1长, j其实不会越界
        int j = start2 + Math.min(len2, k/2) - 1;
        if(nums1[i] < nums2[j]){
            return getKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1));
        }else{
            return getKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1));
        }  
    }
}

感谢以下参考:

知乎用户:windliang 文章 4. Median of Two Sorted Arrays

posted @ 2021-12-30 01:07  红鲤鱼绿鲤鱼与阿米娅  阅读(26)  评论(0)    收藏  举报