原文:4. 寻找两个有序数组的中位数(LeetCode 解题) - 每天一个JavaScript小知识@Js中文网 · 码农进阶题库

原文地址:https://www.javascriptc.com/interview-tips/zh_cn/leetcode/leetcode-javascript-solution-004/

题目描述:

难度:Hard

相关话题:数组二分查找分治算法

给定两个大小为 m 和 n 的有序数组 nums1nums2

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为O(log(m + n))。

你可以假设 nums1nums2 不会同时为空。

示例 1:

nums1 = [1, 3]
nums2 = [2]

则中位数是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

思路:

对于中位数,如果我们能将一半的小的数字放左边,另一半大的数字放右边,那么如果他们的数字总和为偶数,就是(小堆的最大值+大堆的最小值)/2; 如果是奇数,那么就是小堆的最大值

因此,如何将它们分割成了问题的关键。

我们先选择nums1的分割点partition1Math.floor((m+n)/2),这里mnums1.lengthnnums2.length,由于两边的数量要平衡, 因此对nums2的分割点partition2也可以确定,为Math.floor((m+n+1)/2)-partition1

因为是有序的,nums左侧一定小于右侧,因此需要检查分割后的nums1左边的最大值是否能小于等于nums2右边的最小值,并且nums2左边的最大值是否小于等于nums1右边的最小值;

如果能达到这两个条件,说明分割是成功的,可以直接求出中位值;

如果nums1左侧最大值大于nums2右侧最小值,说明nums1的分割点还需要左移;

如果nums2左侧的最大值大于nums1右侧最小值,说明nums2的分割点还需要左移,也就是nums1的分割点需要右移。

/**
 * @来源: Javascript中文网 - 前端进阶资源教程 https://www.javascriptc.com/
 * @介绍:一个致力于帮助开发者用代码改变世界为使命的平台,每天都可以在这里找到技术世界的头条内容
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
var findMedianSortedArrays = function(nums1, nums2) {
  let x=nums1.length,y=nums2.length
  if(x>y){
    return findMedianSortedArrays(nums2,nums1)
  }
  let lo=0,hi=x
  while(lo<=hi){
    // partition1表示nums1的分割点,分割为左右两边;
    // partition2表示nums2的分割点,分割为左右两边;
    // 分割后的数量上,nums1左+nums2左===nums1右+nums2右 (±[-1~1])
    let partition1=Math.floor((lo+hi)/2)
    let partition2=Math.floor((x+y+1)/2)-partition1
    let left1=partition1===0 ? -Infinity : nums1[partition1-1],
        left2=partition2===0 ? -Infinity : nums2[partition2-1]

    let right1=partition1===x ? Infinity : nums1[partition1],
        right2=partition2===y ? Infinity : nums2[partition2]
    // 最终目的是nums1左全部小于nums2右;nums2左全部小于nums1右
    if(left1 <= right2 && left2<=right1){
      if((x+y)%2===0){
        return (Math.max(left1,left2)+Math.min(right1,right2))/2
      }else{
        return Math.max(left1,left2)
      }
    }else if(left1>right2){
      hi=partition1-1
    }else{
      lo=partition1+1
    }
  }
};