leetcode - 4. Median of Two Sorted Arrays
Description
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
Solution
Merge Sort
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)
Binary Search
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)
Divide and conquer
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)
Code
Merge Sort
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)
Binary Search
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
Divide and Conquer
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)
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!