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)).
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
这题最直接的思路就是按 merge two sorted array 的办法,数出来一半的数字。但是那个时间复杂度是 O(m + n)。题目要求 O(log(m+n))
第一个思路是看了九章来的。先看截图
做法就是在 A, B 两数组中各取第 k/2 个数,比一下 ,小的那边就把所有那个位置之前的数都淘汰了。corner case 就是如果某个数组中(比如说 A[])剩下的数不足 k/2 咋办?直接扔掉另外一边的数(B[])。因为即使A[]里面剩下的数都比 B 里的小,因为不足 k/2 个,被扔掉的 B 里面的 k/2 个数肯定不会是总体第 k 位的数。
时间复杂度 O(log(m+n))。程序:
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
length = len(nums1) + len(nums2)
if length % 2 == 1:
return self.findKth(nums1, 0, nums2, 0, (length + 1) // 2) * 1.0
else:
return (self.findKth(nums1, 0, nums2, 0, length // 2)
+ self.findKth(nums1, 0, nums2, 0, length // 2 + 1)) / 2.0
def findKth(self, A, idxA, B, idxB, k):
if k == 1:
if idxA >= len(A):
return B[idxB]
elif idxB >= len(B):
return A[idxA]
else:
return min(A[idxA], B[idxB])
offset = k // 2 - 1
if idxA + offset >= len(A):
return self.findKth(A, idxA, B, idxB + offset + 1, k - k // 2)
elif idxB + offset >= len(B):
return self.findKth(A, idxA + offset + 1, B, idxB, k - k // 2)
elif A[idxA + offset] < B[idxB + offset]:
return self.findKth(A, idxA + offset + 1, B, idxB, k - k // 2)
else:
return self.findKth(A, idxA, B, idxB + offset + 1, k - k // 2)
第二个思路的时间复杂度没有达到要求,但是能 AC,时间复杂度 O(log(range)∗(log(n)+log(m)))
思路就是对值二分。程序如下。但是二分比较tricky,想了一阵才明白,在这样的写法下,为什么 二分出来的数值, 肯定是两数组中的某一个数。只能背下来了。 while lo < hi ... if count >= k hi = mid else lo = mid + 1
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
length = len(nums1) + len(nums2)
if length % 2 == 1:
return self.findKth(nums1, nums2, (length + 1) // 2) * 1.0
else:
return (self.findKth(nums1, nums2, length // 2)
+ self.findKth(nums1, nums2, length // 2 + 1)) / 2.0
def findKth(self, A, B, k):
if not A:
return B[k - 1]
elif not B:
return A[k - 1]
lo, hi = min(A[0], B[0]), max(A[-1], B[-1])
while lo < hi: # 死记硬背
mid = (lo + hi) // 2 #
if self.countLessEqual(A, B, mid) >= k: #
hi = mid #
else: #
lo = mid + 1 #
return lo
def countLessEqual(self, A, B, value): # 算小于等于 value 的元素的个数
import bisect
return bisect.bisect(A, value) + bisect.bisect(B, value)
第三个方法是最好的,有视频教程:https://www.youtube.com/watch?v=LPFhl65R7ww
文字解释:https://leetcode.com/problems/median-of-two-sorted-arrays/discuss/2481/
时间复杂度 O( log( min(m,n) ) )
来张截图

思路就是,短的数组为x,长的数组为y,在x中切一刀,相应的在一种切一刀。然后比较大小看是不是切对了,不对的话二分下一个下刀的位置。
程序
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
import sys
if len(nums1) == 0 and len(nums2) == 0:
return 0
m, n = len(nums1), len(nums2)
if m > n:
return self.findMedianSortedArrays(nums2, nums1)
lo, hi = 0, m
while lo <= hi:
cutIdx1 = (lo + hi) // 2
cutIdx2 = (m + n + 1) // 2 - cutIdx1
if cutIdx1 == 0:
maxLeft1 = nums2[cutIdx2 - 1]
else:
maxLeft1 = nums1[cutIdx1 - 1]
maxLeft1 = -sys.maxint - 1 if cutIdx1 == 0 else nums1[cutIdx1 - 1] # 这几行是为了处理 corner cases
maxLeft2 = -sys.maxint - 1 if cutIdx2 == 0 else nums2[cutIdx2 - 1] #
minRight1 = sys.maxint if cutIdx1 == m else nums1[cutIdx1] #
minRight2 = sys.maxint if cutIdx2 == n else nums2[cutIdx2] #
if maxLeft1 > minRight2:
hi = cutIdx1 - 1
elif maxLeft2 > minRight1:
lo = cutIdx1 + 1
else:
## maxLeft1 <= minRight2 and maxLeft2 <= minRight1. Found solution
if (m + n) % 2 == 1:
return max(maxLeft1, maxLeft2) * 1.0
else:
return (max(maxLeft1, maxLeft2) + min(minRight1, minRight2) ) / 2.0
print lo, hi
return 0
Last updated
Was this helpful?