[Week 6] LeetCode 4. Median of Two Sorted Arrays

15 篇文章 0 订阅
13 篇文章 0 订阅

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)),嗯没错应该是用二分法了,如果是只有一个数组的话,我想大家看到这里会锤我一把骂我浪费大家时间了。这题是在两个已排序的数组中,找到两个数组中所有元素的中位数,也就是说需要考虑奇数和偶数个元素的情况。那我们不妨把问题简化一下,寻找两个数组中的Kth元素如何?在这个题K=(m+n+1)/2K=(m+n+2)/2,我们不妨验证一下:(这里的/C中的整数除法运算哦)

  1. 假设len(nums1)=2len(nums2)=1,那么K=2
  2. 假设len(nums1)=2len(nums2)=2,那么K=2和3

那怎么在两个有序数组中寻找Kth元素呢?

我们先找到两个数组中(K/2)th元素,分别为ab,分以下情况讨论:

  1. a < b,那就代表着nums1中前K/2个元素一定不存在中位数。

  2. a > b,那就代表着nums2中前K/2个元素一定不存在中位数。

  3. a = b,那我们好像就得到答案了?

也就是说,我们每次都淘汰K/(2^k)个元素(k是我们处理的次数),然后把剩余的元素进行上述操作,即递归操作。有的同学看到这里要开始怼我了,说两个数组不一定有K/2个元素你怎么说?那我们可以这样处理嘛(先把刀放下),假设第一个数组元素小于K/2,我们可以让a=INT_MAX,为什么呢?同样道理嘛,如果len(nums1)<K/2,就代表nums2的前K/2个元素一定不存在中位数,为什么?反证法走起!要让其存在中位数,则len(nums1)+K/2 > K,做不到吧?

现在说说边界条件,什么时候应该停止呢?

  1. 当你把某个数组淘汰完后,也就是你只需要在剩下的数组上,使用numsx[begin+K/(2^(k-1))]找到它了。
  2. 否则,当K/(2^(k-1)) == 1时,意味着我们只需要比较两个数组段(因为我们把数组不断地切割)的首元素就好,找到最小的那个!

到这里我们把findKth描述完了,最后只需要比较一下K1K2,如果相等我们就没必要找两次了嘛!

废话不多说,上代码!(希望大家好好想想数组定位的下标为什么这么写?因为我的表达能力有限,无法给你们说出个所以然)

Code

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
      int m1 = (nums1.size() + nums2.size() + 1) / 2,
      m2 = (nums1.size() + nums2.size() + 2) / 2;

      if (m1 == m2) return findKthNum(nums1, 0, nums2, 0, m1);
      else return (findKthNum(nums1, 0, nums2, 0, m1) + findKthNum(nums1, 0, nums2, 0, m2)) / 2.0;
    }

private:
    int findKthNum(vector<int>& nums1, int i, vector<int>& nums2, int j, int k) {
      if (i >= nums1.size()) return nums2[j + k - 1];
      if (j >= nums2.size()) return nums1[i + k - 1];
      if (k == 1) return min(nums1[i], nums2[j]);
      int mid1 = i + k / 2 - 1 < nums1.size() ? nums1[i + k / 2 - 1] : INT_MAX;
      int mid2 = j + k / 2 - 1 < nums2.size() ? nums2[j + k / 2 - 1] : INT_MAX;
      if (mid1 < mid2) {
        return findKthNum(nums1, i + k / 2, nums2, j, k - k / 2);
      } else {
        return findKthNum(nums1, i, nums2, j + k / 2, k - k / 2);
      }
    }
};

复杂度

上述题解中我们也说到,每次我们都淘汰K/(2^k)个元素,虽然我们有m+n个元素,但事实上如果K < m+n,我们接触到的数组范围实际上是K呀,(这里我不太确定),但是我们算法的上界确实是O(log(m+n))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值