解法一:合并数组
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
mergedNums := mergeTwoArray(nums1, nums2)
if len(mergedNums)%2 == 0{
mid1 := float64(mergedNums[len(mergedNums)/2])
mid2 := float64(mergedNums[len(mergedNums)/2-1])
return (mid1+mid2)/2
}else if len(mergedNums)%2 == 1{
return float64(mergedNums[len(mergedNums)/2])
}
return 0
}
func mergeTwoArray(nums1 []int, nums2 []int) []int{
p1, p2 := 0, 0
res := []int{}
for p1 < len(nums1) && p2 < len(nums2) {
n1 := nums1[p1]
n2 := nums2[p2]
if n1 < n2{
res = append(res, n1)
p1++
}else {
res = append(res, n2)
p2++
}
}
if p1 == len(nums1) {
res = append(res, nums2[p2:]...)
}
if p2 == len(nums2) {
res = append(res, nums1[p1:]...)
}
return res
}
- 时间复杂度:O(m+n),m,n为两个数组的长度
- 空间复杂度:O(m+n),额外申请了一个合并后的数组空间
解法二:双指针,优化空间
不需要合并两个有序数组,只要找到中位数的位置即可。由于两个数组的长度已知,因此中位数对应的两个数组的下标之和也是已知的。维护两个指针,初始时分别指向两个数组的下标 0 的位置,每次将指向较小值的指针后移一位(如果一个指针已经到达数组末尾,则只需要移动另一个数组的指针),直到到达中位数的位置。
根据中位数的定义,当 m+n 是奇数时,中位数是两个有序数组中的第 (m+n)/2 个元素,当 m+n 是偶数时,中位数是两个有序数组中的第 (m+n)/2 个元素和第 (m+n)/2+1 个元素的平均值。因此,这道题可以转化成寻找两个有序数组中的第 k 小的数,其中 k 为 (m+n)/2 或 (m+n)/2+1。
用 len 表示合并后数组的长度,如果是奇数,我们需要知道第 (len+1)/2 个数就可以了,如果遍历的话需要遍历 int(len/2 ) + 1 次。如果是偶数,我们需要知道第 len/2和 len/2+1 个数,也是需要遍历 len/2+1 次。所以遍历的话,奇数和偶数都需要遍历 len/2+1 次。
func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
m := len(nums1)
n := len(nums2)
totalLen := m + n
var pre, cur int
var index1, index2 int
for i := 0; i<totalLen/2+1; i++{
pre = cur
// case1: nums1和nums2还没遍历完,比较当前指向元素
if index1 < m && index2 < n{
if nums1[index1] < nums2[index2]{
cur = nums1[index1]
index1++
}else{
cur = nums2[index2]
index2++
}
}else if index1 >= m{ // case2: nums1已遍历完,nums2未遍历完
cur = nums2[index2]
index2++
}else if index2 >= n{ // case3: nums2已遍历完,nums1未遍历完
cur = nums1[index1]
index1++
}
}
if totalLen %2 == 0{ // 偶数长度中位数计算
return float64(pre + cur)/2.0
}
return float64(cur)
}
- 时间复杂度:O(m+n),m,n为两个数组的长度
- 空间复杂度:O(1)