来源:力扣(LeetCode)
链接:寻找两个正序数组的中位数
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目描述
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
示例
- 示例1
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
- 示例2
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
- 示例3
输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000
- 示例4
输入:nums1 = [], nums2 = [1]
输出:1.00000
- 示例5
输入:nums1 = [2], nums2 = []
输出:2.00000
提示:
nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106
进阶:
你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?
算法
- 暴力解法(O(n^2))
合并——>排序——>找中位数
代码示例
package main
import "fmt"
// 冒泡排序
func BubbleSort(num []int) []int {
for n := len(num) - 1; n >= 1; n-- { // 对比多少轮; n表示每轮对比次数
for i := 0; i < n; i++ { // 表示需要对比的元素的索引
if num[i] > num[i+1] {
num[i], num[i+1] = num[i+1], num[i]
}
}
}
return num
}
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
// 合并
nums1 = append(nums1, nums2...)
// 排序
nums := BubbleSort(nums1)
// 求中位数
var mid float64
if len(nums) % 2 == 0 { // 偶数个
mid = (float64(nums[(len(nums)/2)-1]) + float64(nums[len(nums)/2])) / 2
} else { // 奇数个
mid = float64(nums[len(nums) / 2])
}
return mid
}
func main() {
nums1 := []int{1,3}
nums2 := []int{2}
mid1 := findMedianSortedArrays(nums1, nums2)
fmt.Println(mid1)
nums3 := []int{1, 4}
nums4 := []int{3, 2}
mid2 := findMedianSortedArrays(nums3, nums4)
fmt.Println(mid2)
nums5 := []int{0, 0}
nums6 := []int{0, 0}
mid3 := findMedianSortedArrays(nums5, nums6)
fmt.Println(mid3)
nums7 := []int{2}
nums8 := []int{}
mid4 := findMedianSortedArrays(nums7, nums8)
fmt.Println(mid4)
}
- 查找第k小数(O(log(m+n)))
这个题目可以归结到寻找第k小(大)元素问题,思路可以总结如下:取两个数组中的第k/2个元素进行比较,如果数组1的元素小于数组2的元素,则说明数组1中的前k/2个元素不可能成为第k个元素的候选,所以将数组1中的前k/2个元素去掉,组成新数组和数组2求第k-k/2小的元素,因为我们把前k/2个元素去掉了,所以相应的k值也应该减小。另外就是注意处理一些边界条件问题,比如某一个数组可能为空或者k为1的情况。
代码示例
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
def findKthElement(arr1,arr2,k):
len1,len2 = len(arr1),len(arr2)
if len1 > len2:
return findKthElement(arr2,arr1,k)
if not arr1:
return arr2[k-1]
if k == 1:
return min(arr1[0],arr2[0])
i,j = min(k//2,len1)-1,min(k//2,len2)-1
if arr1[i] > arr2[j]:
return findKthElement(arr1,arr2[j+1:],k-j-1)
else:
return findKthElement(arr1[i+1:],arr2,k-i-1)
l1,l2 = len(nums1),len(nums2)
left,right = (l1+l2+1)//2,(l1+l2+2)//2
return (findKthElement(nums1,nums2,left)+findKthElement(nums1,nums2,right))/2