Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.
The overall run time complexity should be O(log (m+n)).
Example 1:
Input: nums1 = [1,3], nums2 = [2]
Output: 2.00000
Explanation: merged array = [1,2,3] and median is 2.
Example 2:
Input: nums1 = [1,2], nums2 = [3,4]
Output: 2.50000
Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.
Constraints:
nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-10^6 <= nums1[i], nums2[i] <= 10^6
Calculate the final position of the median, and merge 2 sorted list to find out the median.
Time complexity: o ( n + m ) o(n+m) o(n+m)
Space complexity: o ( 1 ) o(1) o(1)
If the number of merged list is even, then median is len // 2 - 1
and len // 2
, if it’s odd, the median is len // 2
To find the len // 2
th element, we could find how many numbers there are that are smaller than current number, and do a binary search to find the target.
Time complexity: o ( log ( n u m s ) ∗ log ( m + n ) ) o(\log (nums) * \log (m+n)) o(log(nums)∗log(m+n))
Space complexity: o ( 1 ) o(1) o(1)
Solved after help.
For the median, it’s like finding the kth
element in a sorted list. The basic idea is, the left half of the array with smaller median can never contain the final median. (Because by merging another list, the median is for sure larger)
So if k
is smaller than the sum of left halfs, we discard the right half of the array with larger median, otherwise we discard the left half of the array with smaller median.
Note: if the left halfs contain k
numbers, we still need to discard the left half of the array with smaller median, because the final median is for sure larger than the smaller median.
Time complexity: o ( log ( m + n ) ) o(\log (m+n)) o(log(m+n))
Space complexity: o ( 1 ) o(1) o(1)
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
m, n = len(nums1), len(nums2)
final_len = m + n
p1, p2 = 0, 0
p = 0
cur_num = None
candidates = []
while p1 < m or p2 < n:
if p == final_len // 2 + 1:
candidates.append(cur_num)
if p == final_len // 2 and final_len % 2 == 0:
candidates.append(cur_num)
if p1 < m and p2 < n:
if nums1[p1] <= nums2[p2]:
cur_num = nums1[p1]
p1 += 1
else:
cur_num = nums2[p2]
p2 += 1
elif p1 < m:
cur_num = nums1[p1]
p1 += 1
elif p2 < n:
cur_num = nums2[p2]
p2 += 1
p += 1
if p == final_len // 2 + 1:
candidates.append(cur_num)
if p == final_len // 2 and final_len % 2 == 0:
candidates.append(cur_num)
return sum(candidates) / len(candidates)
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
def get_smaller_number(nums: list, target: int) -> int:
left, right = 0, len(nums) - 1
while left < right:
mid = (left + right + 1) >> 1
if nums[mid] >= target:
right = mid - 1
else:
left = mid
mid = (left + right + 1) >> 1
if not nums or nums[mid] >= target:
return 0
return mid + 1
def find_num(nums1: list, nums2: list, k: int) -> int:
"""
Find the num that there are k numbers that are smaller than num
"""
# be careful of empty lists
if not nums1:
left, right = nums2[0], nums2[-1]
elif not nums2:
left, right = nums1[0], nums1[-1]
else:
left, right = min(nums1[0], nums2[0]), max(nums1[-1], nums2[-1])
while left < right:
mid = (left + right + 1) >> 1
if get_smaller_number(nums1, mid) + get_smaller_number(nums2, mid) > k:
right = mid - 1
else:
left = mid
return (left + right + 1) >> 1
m, n = len(nums1), len(nums2)
final_len = m + n
if final_len % 2 == 0:
res1, res2 = find_num(nums1, nums2, final_len // 2), find_num(nums1, nums2, final_len // 2 - 1)
return (res1 + res2) / 2
else:
res = find_num(nums1, nums2, final_len // 2)
return res
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
def find_kth(left1: int, right1: int, left2: int, right2: int, k: int) -> int:
if left1 > right1:
return nums2[left2 + k - 1]
if left2 > right2:
return nums1[left1 + k - 1]
i1 = (left1 + right1) >> 1
i2 = (left2 + right2) >> 1
if i1 - left1 + 1 + i2 - left2 + 1 <= k:
if nums1[i1] < nums2[i2]:
return find_kth(i1 + 1, right1, left2, right2, k - (i1 - left1 + 1))
else:
return find_kth(left1, right1, i2 + 1, right2, k - (i2 - left2 + 1))
else:
if nums1[i1] > nums2[i2]:
return find_kth(left1, i1 - 1, left2, right2, k)
else:
return find_kth(left1, right1, left2, i2 - 1, k)
m, n = len(nums1), len(nums2)
if (m + n) % 2 == 0:
return (find_kth(0, m - 1, 0, n - 1, (m + n) // 2) + find_kth(0, m - 1, 0, n - 1, (m + n) // 2 + 1)) / 2
else:
return find_kth(0, m - 1, 0, n - 1, (m + n) // 2 + 1)