Leetcode 0004: Median of Two Sorted Arrays

题目描述:

Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.
Follow up: 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.

Example 3:

Input: nums1 = [0,0], nums2 = [0,0]
Output: 0.00000

Example 4:

Input: nums1 = [], nums2 = [1]
Output: 1.00000

Example 5:

Input: nums1 = [2], nums2 = []
Output: 2.00000

Constraints:

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

Time complexity: O(log (m+n))
Binary Search 二分:
给定两个有序的数组,找中位数(n + m) / 2,等价于找第k小的元素,k = (n + m) / 2

  1. 当总长度len为偶数时,中位数为 第len/2小的数和第len/2 + 1小的数的平均值。
  2. 当总长度len为奇数时,中位数为 第len/2 + 1小的数。

问题变为如何在两个有序数组中找到第k小的数,我们先从 nums1 和 nums2 中各取前 k/2 个元素

  1. 如果第一个数组nums1 第 k/2小数的大于 第二个数组nums2 第 k/2小数,即:nums1[k/2−1] > nums2[k/2−1]。则表示nums2 中的前 k/2 个元素一定都小于第 k 小的数。所以我们可以先取出这些数,然后在剩下的数中找第 k−⌊k/2⌋ 小数.
  2. 同理,如果第一个数组nums1 第 k/2小数的小于 第二个数组nums2 第 k/2小数,即:nums1[k/2−1] < nums2[k/2−1]。则表示nums1 中的前 k/2 个元素一定都小于第 k 小的数。所以我们可以先取出这些数,然后在剩下的数中找第 k−⌊k/2⌋ 小数.

考虑边界情况:

  1. 如果任意一个数组总长度小于 k/2,例如 nums1 长度 n < k/2. 则需要考虑各个数组的有效长度对与数组 nums1 (起始点为i)有效长度 si = Math.min(nums1.length, i+k/2);
    数组 nums2 (起始点为j)有效长度 sj = j + k - k/2。
  2. 当nums1[si - 1] > nums2[sj - 1]时,则表示target第k小的数一定在[i,n]与[sj,m]中
  3. 当nums1[si - 1] <= nums2[sj - 1]时,则表示target第k小的数一定在[si,n]与[j,m]中
class Solution {
    
    
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    
    
        int len = nums1.length + nums2.length;
        if(len%2 == 0){
    
    
            int left = find(nums1, 0, nums2, 0, len/2);
            int right = find(nums1, 0, nums2, 0, len/2+1);
            return (left+right)/2.0;
        }else{
    
    
            return (double)find(nums1, 0, nums2, 0, len/2+1);
        }
    }
    
    int find(int[] nums1, int i, int[] nums2, int j, int k){
    
    
        //默认第一个是小的
        if(nums1.length - i > nums2.length-j){
    
    
            return find(nums2, j, nums1, i, k);
        }
        if(nums1.length == i){
    
    
            return nums2[j+k-1];
        }
        //当取第1个元素
        if(k == 1) return Math.min(nums1[i],nums2[j]);
        int si = Math.min(nums1.length, i+k/2);
        int sj = j+k-k/2;
        if(nums1[si-1] > nums2[sj-1]){
    
    
            return find(nums1, i, nums2, sj, k-(sj-j));
        }else{
    
    
            return find(nums1, si, nums2, j, k-(si-i));
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43946031/article/details/113781099