【Leetcode】两个有序数组,求第k大的数

在这里插入图片描述
双指针:

def func(num1,num2,k):
    i,j,n = 0,0,0
    while i<len(num1) or j<len(num2):
        n += 1
        if i<len(num1) and j<len(num2):
            if num1[i] < num2[j]:
                if n == k:
                    return num1[i]
                i += 1
            else:
                if n == k:
                    return num2[j]        
                j += 1                    
        elif i<len(num1):
            if n == k:
                return num1[i]
            i += 1                
        else:
            if n == k:
                return num2[j]       
            j += 1                 


print(func([1,5,8],[2,3,4],6))

方法二:
要找第两个数组的第k大,可以找num1[k/2], 和num2[k/2],如果这俩相等,那他俩就是第k大。
比如在下面的俩数组中找第4大的,我们发现num1的第2个和num2的第2个相等,那就返回 [3] 就好了。

num1 = [1,3,5]
num2 = [2,3,4]

如果num1的第2个 > num2的第2个,那就不要num2的前俩了,因为肯定不是第4大。然后把num2剩余的元素,也就是[4]放入下一次递归,此时k = 4 - 2 = 2,因为已经排除俩了。

num1 = [1,3,5]
num2 = [1,2,4]

反之亦然,这里值得注意的是,如果k是奇数,由于python取整的原因,k/2需要改成:num1[k//2], 和num2[k-k//2]

再由于python 从0开始计数,再改成 num1[k//2-1], 和num2[k-k//2-1]

整体代码如下:

def func2(num1,num2,k):
    if k == 1:
        return min(num1[0], num2[0])
    if not num1:
        return num2[k-1]
    if not num2:
        return num1[k-1]
    k1 = k // 2
    k2 = k - k1
    if num1[k1-1] > num2[k2-1]:
        return func2(num1, num2[k2:], k-k2)
    else:
        return func2(num1[k1:], num2, k-k1)

print(func2([1,5,8],[2,3,4],6))

猜你喜欢:👇🏻
【Leetcode】大神总结的所有TopK问题模板(基于快速排序)
【Leetcode】二分法左侧边界右侧边界模板
【Leetcode】338. 比特位计数(动态规划)

在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以使用二分查算法来解决这个问题。 首先,我们可以将两个组合并成一个有序数组,然后出中位。但是,这个方法的时间复杂度为 $O(m + n)$,不符合题目要。因此,我们需要寻一种更快的方法。 我们可以使用二分查算法在两个组中分别到一个位置,使得这个位置将两个组分成的左右两部分的元素个之和相等,或者两部分的元素个之差不超过 1。这个位置就是中位所在的位置。 具体来说,我们分别在两个组中二分查,假设现在在第一个组中到了一个位置 $i$,那么在第二个组中对应的位置就是 $(m + n + 1) / 2 - i$。如果 $i$ 左边的元素个加上 $(m + n + 1) / 2 - i$ 左边的元素个等于 $m$ 个,或者 $i$ 左边的元素个加上 $(m + n + 1) / 2 - i$ 左边的元素个等于 $m + 1$ 个,则这个位置就是中位所在的位置。 具体的实现可以参考以下 Java 代码: ```java public double findMedianSortedArrays(int[] nums1, int[] nums2) { int m = nums1.length, n = nums2.length; if (m > n) { // 保证第一个组不大于第二个组 int[] tmp = nums1; nums1 = nums2; nums2 = tmp; int t = m; m = n; n = t; } int imin = 0, imax = m, halfLen = (m + n + 1) / 2; while (imin <= imax) { int i = (imin + imax) / 2; int j = halfLen - i; if (i < imax && nums2[j - 1] > nums1[i]) { imin = i + 1; // i 太小了,增大 i } else if (i > imin && nums1[i - 1] > nums2[j]) { imax = i - 1; // i 太大了,减小 i } else { // i 是合适的位置 int maxLeft = 0; if (i == 0) { // nums1 的左边没有元素 maxLeft = nums2[j - 1]; } else if (j == 0) { // nums2 的左边没有元素 maxLeft = nums1[i - 1]; } else { maxLeft = Math.max(nums1[i - 1], nums2[j - 1]); } if ((m + n) % 2 == 1) { // 总元素个是奇 return maxLeft; } int minRight = 0; if (i == m) { // nums1 的右边没有元素 minRight = nums2[j]; } else if (j == n) { // nums2 的右边没有元素 minRight = nums1[i]; } else { minRight = Math.min(nums1[i], nums2[j]); } return (maxLeft + minRight) / 2.0; } } return 0.0; } ``` 时间复杂度为 $O(\log\min(m, n))$。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值