NO.4 寻找两个有序数组的中位数 困难
思路一:暴力法 直接合并两个有序数组,然后根据奇偶性找到中位数。但是这种笨办法不能满足时间复杂度的要求。
1 | public double findMedianSortedArrays(int[] nums1, int[] nums2) { |
时间复杂度:O(n+m)
思路二:二分法 根据题目中要求的时间复杂度O(log(m+n))想到要使用二分法。因此我们就不能合并两个数组了。
其实根据上一题我们就不难发现是否合并两个数组并不重要,我们知道两个数组的长度总和是count,知道中位数是第count/2个或者(num[count/2-1]+num[count/2])/2.0就够了。我们困难的是怎样在不同的数组之间进行二分法。
我们换个思考方向:我们把“找中位数”看作是”找第k小的数“的特殊情况。可以充分利用数组是有序的这一特点去找第k小的数,每次排除掉k/2个元素。
看一个”寻找第k小的数“例子:
- 假设我们现在要从A和B两个有序数组中找第7小的数字,我们先比较两个数组的第k/2个元素的大小。3<4所以A数组[1,2,3]这三个元素必然不是第7小的数字,所以排除掉。
- 已经排除了3个,所以我们现在需要在两个数组剩余的部分寻找第4小的数。同样的,我们先比较两个数组剩余元素的第k/2个元素的大小,5>3所以B数组[1,3]这两个元素必然不是第4小的元素,所以排除。
- 我们继续在两个数组剩余部分寻找第2小的数。我们比较两个数组剩余元素的第k/2个元素,4=4去掉哪个都行,我们统一处理即可,去掉B的4元素。
- 此时k=1,只需要判断两个数组剩余部分的第一个元素哪个小即可,找到A数组的4就是第7小的数。
按照上述例子中的算法,会出现一个问题:每次循环都需要取两个数组剩余部分的第k/2个元素进行比较,如果此时某个数组剩余部分不足k/2个元素怎么办???
再看一个例子:
- 依然是找第7小的数,但是B数组不能取到第k/2个元素,此时取出B数组的最后一个元素和A数组的第k/2个元素作比较即可。
- 此时B数组已空,所以直接返回A数组的第5个元素即可。
回到本题“寻找中位数”!有了这个”寻找第k小的数“的算法,去寻找两个有序数组的中位数就容易多了。可以看到无论是找第奇数个还是找第偶数个对上述算法并无影响,最终都会因为k==1或一个数组空了,返回寻找结果。
最终,“寻找中位数”这个算法我们就以递归的方式进行,为了防止数组长度小于k/2,所以每次比较数组的第min(k/2,数组剩余len)个元素,将小的那部分排除之后,将两个新数组继续送入递归,并将k减去排除的元素个数。递归的出口就是k==1或其中一个数组剩余长度为0。
1 | public double findMedianSortedArrays(int[] nums1, int[] nums2) { |
时间复杂度:O(log(n+m))
本人菜鸟,有错误请告知,感激不尽!