Leetcode4 寻找两个正序数组的中位数

55 阅读2分钟

leetcode.cn/problems/me…

image.png

解法一:合并数组

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)