4.寻找两个有序数组的中位数

题目

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

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

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

一. 连接数组后排序

将两个数组连接起来后进行排序,返回排序后的数组的中位数。

js实现

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
var findMedianSortedArrays = function(nums1, nums2) {
  var result = nums1.concat(nums2)
  result.sort((a, b) => a - b)
  if (result.length % 2) {
    return result[(result.length-1)/2]
  } else {
    return (result[result.length/2-1] + result[result.length/2]) / 2
  }
};

复杂度分析

时间复杂度:O((m+n)*log(m+n))

空间复杂度:O(m+n)

测试结果

✔ Accepted
  ✔ 2085/2085 cases passed (156 ms)
  ✔ Your runtime beats 91.84 % of javascript submissions
  ✔ Your memory usage beats 49.74 % of javascript submissions (39.5 MB)

二. 迭代去除最值

两个数组的中位数与去掉最小值和最大值之后的两个数组相等,当其中一个数组为空时,返回另一个数组的中位数即可。

js实现

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
var findMedianSortedArrays = function(nums1, nums2) {
  while (nums1.length + nums2.length > 2 && nums1.length && nums2.length) {
    var startd1 = true
    if (nums1[0] > nums2[0]) {
      startd1 = false
    }
    var endd1 = true
    if (nums1[nums1.length-1] < nums2[nums2.length-1]) {
      endd1 = false
    }
    if (startd1) {
      nums1.shift()
    } else {
      nums2.shift()
    }
    if (endd1) {
      nums1.pop()
    } else {
      nums2.pop()
    }
  }
  if (!nums1.length) {
    if (nums2.length%2) {
      return nums2[(nums2.length-1) / 2]
    } else {
      return (nums2[nums2.length/2-1] + nums2[nums2.length/2]) / 2
    }
  }
  if (!nums2.length) {
    if (nums1.length%2) {
      return nums1[(nums1.length-1) / 2]
    } else {
      return (nums1[nums1.length/2-1] + nums1[nums1.length/2]) / 2
    }
  }
  
  return (nums1[0] + nums2[0]) / 2
};

复杂度分析

时间复杂度:O(min(m, n))

空间复杂度:O(1)

测试结果

✔ Accepted
  ✔ 2085/2085 cases passed (188 ms)
  ✔ Your runtime beats 63.95 % of javascript submissions
  ✔ Your memory usage beats 97.83 % of javascript submissions (38.5 MB)

三. 中位数定义与二分查找结合

根据中位数的定义,将两个数组各自从某处划分为左右两部分,如果两个数组的左边部分两数组的长度之和与右边部分两数组的长度之和相等,且两个数组左边部分的最大值不大于右边部分的最小值,则中位数为左边最大值与右边最小值的平均。

由于左右部分长度相等,因此我们只需要确定第一个数组的划分位置,使用二分法查找此位置即可。

js实现

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
var findMedianSortedArrays = function(nums1, nums2) {
  if (nums1.length > nums2.length) {
    var temp = nums1
    nums1 = nums2
    nums2 = temp
    // [m, n] = [n, m]
  }
  var m = nums1.length
  var n = nums2.length
  // 定义数组1的左右边界
  var left = 0
  var right = m
  // 一半长度
  var half = Math.floor((m + n + 1) / 2)
  while (left <= right) {
    var i = Math.floor((left + right) / 2)
    var j = half - i
    if (i < right && nums1[i] < nums2[j-1]) {
      left = i + 1
    } else if (i > left && nums2[j] < nums1[i-1]) {
      right = i - 1
    } else {
      var leftMax
      if (i === 0) {
        leftMax = nums2[j-1]
      } else if (j === 0) {
        leftMax = nums1[i-1]
      } else {
        leftMax = Math.max(nums1[i-1], nums2[j-1])
      }

      if ((m + n) % 2) {
        return leftMax
      }

      var rightMin
      if (i === m) {
        rightMin = nums2[j]
      } else if (j === n) {
        rightMin = nums1[i]
      } else {
        rightMin = Math.min(nums1[i], nums2[j])
      }

      return (leftMax + rightMin) / 2
    }
  }
};

复杂度分析

时间复杂度:O(log(min(m, n)))

空间复杂度:O(1)

测试结果

✔ Accepted
  ✔ 2085/2085 cases passed (124 ms)
  ✔ Your runtime beats 99.18 % of javascript submissions
  ✔ Your memory usage beats 94.52 % of javascript submissions (38.8 MB)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值