寻找两个正序数组的中位数
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
最优解决方案
二分法的意思是:当你要在一个有序的数组里找一个数,你不用从头到尾一个个去比较,而是可以从中间开始,看看中间的数是不是你要找的。如果是,那就找到了;如果不是,那就看看它比你要找的数大还是小。如果比你要找的数大,那就说明你要找的数在左边;如果比你要找的数小,那就说明你要找的数在右边。然后你再把左边或者右边的部分当成一个新的数组,重复上面的步骤,直到找到你要找的数或者没有剩下任何元素。
举个例子吧:
假设有一个数组 [1, 3, 5, 7, 9] ,你要找 7 这个数。
第一步:从中间开始比较,中间的数是 5 ,不等于 7 ,而且比 7 小,所以我们知道 7 在右边。
第二步:把右边部分 [7, 9] 当成一个新的数组,再从中间开始比较,中间的数是 7 ,等于我们要找的数,所以我们就找到了。
这样就省去了很多不必要的比较,提高了效率。
- 首先,我们要找到两个数组合并后的中位数,也就是中间的那个数(如果是偶数个,就是中间两个数的平均值)
- 然后,我们想到一个简单的方法,就是把两个数组都排序好,然后从头开始数,数到第 (m+n)/2 + 1 个数就是中位数(如果是偶数个,还要再往后数一个,同理执行)
- 但是这样做太慢了,因为排序本身就要花很多时间
- 所以我们想到一个更快的方法,就是不用排序,直接找到第 (m+n)/2 + 1 个数
- 这样做的关键就是利用两个数组本身已经是正序(从小到大)的这个特点
- 我们可以每次比较两个数组中间位置的那个数(也就是第 k/2 个数),看哪个更小
- 如果 nums1 的中间位置的那个数更小,那么说明 nums1 的前半部分都不可能是第 (m+n)/2 + 1 个数,因为它们都太小了
- 所以我们可以把 nums1 的前半部分删掉,然后在剩下的部分继续找第 (m+n)/2 + 1 - k/2 个数(因为我们已经排除了 k/2 个数)
- 反之如果 nums2 的中间位置的那个数更小,那么说明 nums2 的前半部分都不可能是第 (m+n)/2 + 1 个数,因为它们都太小了
- 所以我们可以把 nums2 的前半部分删掉,然后在剩下的部分继续找第 (m+n)/2 + 1 - k/2 个数(因为我们已经排除了 k/2 个数)
- 这样每次我们都能排除掉一半的候选数字,直到找到第 (m+n)/2 + 1 个数字为止