[LeetCode-Golang] 4. 寻找两个有序数组的中位数

题目

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例 1:

nums1 = [1, 3]
nums2 = [2]

则中位数是 2.0


示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

解题思路

将题目转化为求两个有序数组第k小的数。每次删掉前k/2个数,更新k

参考https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/中的解法三

复杂度分析

时间复杂度O(log(m + n))

空间复杂度O(1) 虽然用了递归,但是是尾递归,所以仍为O(1)

代码

 

func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
    sumLen := len(nums1) + len(nums2)
    if sumLen & 1 == 1 {
        // 总长为奇数
        return float64(findKth(nums1, nums2, (sumLen+1)>>1))
    } else {
        // 总长为偶数
        return float64(findKth(nums1, nums2, sumLen>>1) + findKth(nums1, nums2,(sumLen>>1)+1)) * 0.5
    }
}
func findKth(nums1, nums2 []int, k int) int {
    len1 := len(nums1)
    len2 := len(nums2)
    // 设置nums1为短切片
    if len1 > len2 {
        return findKth(nums2, nums1, k)
    }
    // 如果nums1已经到末尾,直接返回nums2的第k-1个元素
    if len1 == 0 {
        return nums2[k-1]
    }
    // 如果k==1,只要判断两个切片的第0个元素,取最小值
    if k == 1 {
        return minInt(nums1[0], nums2[0])
    }
    // 找到两个切片的第k/2-1个元素,比较大小。注意len(nums1)可能小于k/2
    pos1 := minInt(len1, k>>1) - 1
    pos2 := k>>1 -1
    if nums1[pos1] < nums2[pos2] {
        // 删除nums1的前pos1个元素
        return findKth(nums1[pos1+1:], nums2, k - pos1 -1)
    }
    return findKth(nums1, nums2[pos2+1:], k - pos2 -1)
} 
func minInt(a, b int) int {
    if a < b {
        return a
    }
    return b
}

 

 执行结果

执行用时 :8 ms, 在所有 Go 提交中击败了99.63% 的用户
内存消耗 :5.6 MB, 在所有 Go 提交中击败了100.00%的用户
posted @ 2020-03-15 16:50  世界边境  阅读(205)  评论(0编辑  收藏  举报