Go-Leecode-寻找两个正序数组的中位数(刷题记录)

161 篇文章 12 订阅
本文探讨了如何通过合并两个正序数组并利用中位数计算方法,实现两种解决方案:直接合并后根据数组长度找中位数,以及二分查找分而治之的策略。第一种方法适用于简单情况,第二种则涉及高级搜索技巧。适合理解不同算法思想的开发者。
摘要由CSDN通过智能技术生成

原文地址:Go-Leecode-寻找两个正序数组的中位数(刷题记录)

给定两个长度分别为m、n的正序(从小到大)数组num1和num2,需找出两个正序数组的中位数。

示例一:

输入:nums1 = [1,3], nums2 = [2]输出:2.00000

示例二:

输入:nums1 = [1,2], nums2 = [3,4]输出:2.50000

示例三:

输入:nums1 = [0,0], nums2 = [0,0]输出:0.00000

示例四:

输入:nums1 = [], nums2 = [1]输出:1.00000

示例五:

输入:nums1 = [2], nums2 = []输出:2.00000

提示内容如下:

  1. nums1.length == m。

  2. nums2.length == n。

  3. 0 <= m <= 1000。

  4. 0 <= n <= 1000。

  5. 1 <= m + n <= 2000。

  6. -106 <= nums1[i], nums2[i] <= 106。

从上述示例中分析,当获取到两个正序数组num1和num2时,首先应该做的就是将num1和num2进行合并,之后计算合并后数组的位数,是奇数则取中间的元素,是偶数则取中间两数之和的二分之一。

针对以上分析,现给出解决方案一:

func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
    res := merge(nums1, nums2)
    n := len(res)
    if n == 0 {
        return -1
    }
    
    if n%2 == 0 {
        return float64(res[n/2-1]+res[n/2]) / 2
    }
    
    return float64(res[n/2])
}

func merge(nums1, nums2 []int) []int {
    n1, n2 := len(nums1), len(nums2)
    i, j := 0, 0
    res := make([]int, 0, n1+n2)
    for i < n1 && j < n2 {
        switch {
        case nums1[i] < nums2[j]:
            res = append(res, nums1[i])
            i++
        case nums1[i] > nums2[j]:
            res = append(res, nums2[j])
            j++
        default:
            res = append(res, nums1[i], nums2[j])
            i++
            j++
        }
    }

    if i < n1 {
        res = append(res, nums1[i:]...) 
    }
    
    if j < n2 {
        res = append(res, nums2[j:]...)
    }
    
    return res
}

在网上还找到另外一种类二分查找分而治之的方案,在两个有序数组中查找第k大的数,即nums中索引为k-1的数,在舍弃区域比较值时都要-1处理。

解决方案二:

func findMedianSortedArrays(nums1 []int, nums2 []int) float64 {
    n1, n2 := len(nums1), len(nums2)
    if n1+n2 == 0 {
        return -1
    }
    
    if (n1+n2)%2 == 0 {
        l := findKth(nums1, nums2, (n1+n2)/2)
        r := findKth(nums1, nums2, (n1+n2)/2+1)
        return float64(l+r) / 2
    }
    
    return float64(findKth(nums1, nums2, (n1+n2)/2+1))
}

func findKth(nums1, nums2 []int, k int) int {
    n1, n2 := len(nums1), len(nums2)
    if n1 > n2 {
        n1, n2 = n2, n1
        nums1, nums2 = nums2, nums1
    }

    if n1 == 0 {
        return nums2[k-1]
    }

    if k == 1 {
        return min(nums1[0], nums2[0])
    }

    k1 := min(k/2, n1)
    k2 := k - k1
    switch {
    case nums1[k1-1] < nums2[k2-1]:
        return findKth(nums1[k1:], nums2, k2)
    case nums1[k1-1] > nums2[k2-1]:
        return findKth(nums1, nums2[k2:], k1)
    default:
        return nums1[k1-1]
    }
}

实话实讲,第二种方案真心没看明白。

至此,本次分享就结束了,后期会慢慢补充。

以上仅为个人观点,不一定准确,能帮到各位那是最好的。

好啦,到这里本文就结束了,喜欢的话就来个三连击吧。

扫码关注公众号,获取更多优质内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luyaran

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值