二分查找:力扣4. 寻找两个正序数组的中位数
程序员文章站
2022-06-17 19:50:18
...
1、题目描述:
2、题解:
方法1:暴力法
思路:
1、使用归并的方式,合并两个有序数组,得到一个大的有序数组。大的有序数组的中间位置的元素,即为中位数。
2、不需要合并两个有序数组,只要找到中位数的位置即可。由于两个数组的长度已知,因此中位数对应的两个数组的下标之和也是
已知的。维护两个指针,初始时分别指向两个数组的下标 0 的位置,每次将指向较小值的指针后移一位(如果一个指针已经
到达数组末尾,则只需要移动另一个数组的指针),直到到达中位数的位置。
合并两个有序的数组后找中位数
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
#暴力法,合并两个有序的数组
res = []
m,n = len(nums1),len(nums2)
if m == 0:
if n % 2 == 0:
return (nums2[n//2] + nums2[n // 2 - 1]) / 2
else :
return nums2[n // 2]
if n == 0:
if m % 2 == 0:
return (nums1[m // 2] + nums1[m // 2 - 1]) / 2
else:
return nums1[m // 2]
i ,j = 0,0
while i < m and j < n:
if nums1[i] < nums2[j]:
res.append(nums1[i])
i += 1
else:
res.append(nums2[j])
j += 1
res += nums1[i:] if i < m else nums2[j:]
size = len(res)
if size % 2 == 0:
return (res[size // 2] + res[size // 2 - 1]) / 2
else:
return res[size // 2]
方法2:二分查找
思路:
中位数的定义:当m + n为奇数时,中位数是两个有序数组的第(m+n)/2个元素,当m+n为偶数时,中位数是(m+n)/2、(m+n)/2+1
个元素的平均值。所以可以转化成寻找两个有序数组中的第k小的数,k为(m+n)/2或(m+n)/2+1
- 主要思路:要找到第 k (k>1) 小的元素,那么就取 pivot1 = nums1[k/2-1] 和 pivot2 = nums2[k/2-1] 进行比较
- 这里的 "/" 表示整除
- nums1 中小于等于 pivot1 的元素有 nums1[0 .. k/2-2] 共计 k/2-1 个
- nums2 中小于等于 pivot2 的元素有 nums2[0 .. k/2-2] 共计 k/2-1 个
- 取 pivot = min(pivot1, pivot2),两个数组中小于等于 pivot 的元素共计不会超过 (k/2-1) + (k/2-1) <= k-2 个
- 这样 pivot 本身最大也只能是第 k-1 小的元素
- 如果 pivot = pivot1,那么 nums1[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums1 数组
- 如果 pivot = pivot2,那么 nums2[0 .. k/2-1] 都不可能是第 k 小的元素。把这些元素全部 "删除",剩下的作为新的 nums2 数组
- 由于我们 "删除" 了一些元素(这些元素都比第 k 小的元素要小),因此需要修改 k 的值,减去删除的数的个数
Python代码如下:
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
#二分查找
def getKthElement(k):
index1,index2 = 0,0
while True:
#特殊情况
if index1 == m:
return nums2[index2 + k -1]
if index2 == n:
return nums1[index1 + k - 1]
if k == 1:
return min(nums1[index1],nums2[index2])
#一般情况
newIndex1 = min(index1 + k // 2 - 1,m - 1)
newIndex2 = min(index2 + k // 2 - 1 , n - 1)
pivot1,pivot2 = nums1[newIndex1],nums2[newIndex2]
if pivot1 <= pivot2:
k -= newIndex1 - index1 + 1
index1 = newIndex1 + 1
else:
k -= newIndex2 - index2 + 1
index2 = newIndex2 + 1
m,n = len(nums1),len(nums2)
totalLen = m + n
if totalLen % 2 == 1:
return getKthElement((totalLen + 1) // 2)
else:
return ((getKthElement(totalLen // 2)) + getKthElement(totalLen // 2 + 1)) / 2
3、复杂度分析:
方法1:
时间复杂度:O(M+N),M、N分别为两个数组的长度
空间复杂度:O(M+N)
方法2:
时间复杂度:O(log(M+N)),M、N分别为两个数组的长度
空间复杂度:O(1)