给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
示例 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
提示:
nums1.length == mnums2.length == n0 <= m <= 10000 <= n <= 10001 <= m + n <= 2000-106 <= nums1[i], nums2[i] <= 106
解答:
解法1:
这道题最简单的方法就是对两个数组分别设置两个指针,对数组进行遍历,同时初始化m1和m2用于存储最大的数和第二大的数字,当遍历到i==mid时,就意味着我们已经获取了数组的中位数,然后判断一下,数组是奇数还是偶数,奇数则返回m1,偶数则返回(m1+m2)/2
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
l1, l2 := 0, 0
len1, len2 := len(nums1), len(nums2)
m1, m2 := float64(0.0), float64(0.0)
mid := int((len1 + len2) / 2)
for i := 0; i <= mid; i++ {
if l2 >= len2 || (l1 < len1 && nums1[l1] <= nums2[l2]) {
m2 = m1
m1 = float64(nums1[l1])
l1 += 1
} else {
m2 = m1
m1 = float64(nums2[l2])
l2 += 1
}
}
if (len1+len2)%2 == 0 {
return (m1 + m2) / 2
} else {
return m1
}
}
解法2:
为了进一步降低时间复杂度,对于偶数数组,要寻找第k(数组长度的一半)小的数和第k+1小的数,对于奇数数组,寻找第k+1小的数,设置一个mid指针,判断两个数组中k/2位置上的数字大小,将较小的数字全部排除(他们不可能是中位数),然后修改k=k-k/2(k减去被排除的数字个数),当k=1时,返回两个数组中的最小数字。
特殊情况:当mid大于数组长度导致溢出时,如果溢出的那个数组最后一位数比另一个数组的mid位数字小,排除所有溢出数组中的数字,否则正常进行下一次循环
func kmax(nums1 []int, nums2 []int, k int) int {
for k > 1 {
mid := int(k/2) - 1
if mid+1 > len(nums1) {
if len(nums1) > 0 && nums2[mid] > nums1[len(nums1)-1] {
return nums2[k-len(nums1)-1]
}
nums2 = nums2[mid+1:]
k = k - int(k/2)
continue
}
if mid+1 > len(nums2) {
if len(nums2) > 0 && nums1[mid] > nums2[len(nums2)-1] {
return nums1[k-len(nums2)-1]
}
nums1 = nums1[mid+1:]
k = k - int(k/2)
continue
}
n1, n2 := nums1[mid], nums2[mid]
if n1 <= n2 {
nums1 = nums1[mid+1:]
} else {
nums2 = nums2[mid+1:]
}
k = k - int(k/2)
}
if len(nums2) == 0 {
return nums1[0]
} else if len(nums1) == 0 {
return nums2[0]
} else if nums1[0] <= nums2[0] {
return nums1[0]
} else {
return nums2[0]
}
}
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
k := len(nums1) + len(nums2)
if k%2 == 1 {
k = int(k/2) + 1
return float64(kmax(nums1, nums2, k))
} else {
k = int(k / 2)
res := float64(kmax(nums1, nums2, k)+kmax(nums1, nums2, k+1)) / 2
fmt.Println(kmax(nums1, nums2, k+1))
return res
}
}