【一文解决】寻找两个正序数组的中位数(来源:力扣腾讯精选50题)

这篇博客介绍了如何在O(log(m+n))的时间复杂度内找到两个正序数组的中位数。作者分析了两种解法:一是通过找第K大问题,二是数组分割法。每种方法都详细解释了思路和实现代码,并提供了两种附加解法作为对比。通过这些解法,即使是困难级别的题目也能迎刃而解。
摘要由CSDN通过智能技术生成

【一文搞定】寻找两个正序数组的中位数

最近在努力做题~~

昨天做到一道题没感觉还是挺有难度的……我看了半天终于把题解搞懂了,所以写一篇博客来整理一下~~~

题目描述

这道题来源于力扣题库中的腾讯精选50题

题目描述如下:
在这里插入图片描述
在这里插入图片描述

可以注意到题目难度为困难

虽然评论区有不少大佬吐槽这题目都算困难??
在这里插入图片描述

作为小白直觉自己太菜了……不过没关系,等我们把它搞懂了,这样的题目在我们这儿也就不是困难啦~~~

在我们开动脑筋解决困难之前,先活动活动手指点个一键三连吧~~~~

从题目描述和给出的示例,我们可以大致了解题意是让我们将两个按照正序(升序)排好的数组合并成一个有序的数组,并返回数组的中位数。
在这里插入图片描述

题目分析

什么是中位数?
在这里插入图片描述
根据释义,中位数就是一组数据的中间值:
当这组数的个数为奇数时,中位数就是数组中间的值。
当这组数的个数为偶数时,中位数是数组中间两个数的平均数。

所以,这里我们要注意偶数和奇数两种情况的讨论。

从例子中返回的结果以及给出的代码可以知道方法的返回值为double。

这道题按照基本思路应该是将两个数组合并起来,然后再找中位数。

但是……
在这里插入图片描述
题目要求时间复杂度为O(log(m+n))

大概就是这一把操作让题目的难度瞬间达到了“困难”的等级……

不过,别慌……
在这里插入图片描述
虽然题目要求了时间复杂度,但是从log(m+n)这个时间复杂度看,它反而给了我们一些提示:

你们快看!!!我log()摆明就是要你往二分法看齐的啦!

所以传统的方法1(先进行归并,再找中位数)和方法二(假装归并了再找中位数)都不能达到这个时间复杂度。
(方法一和方法二作为附加解法在后面给出)

其实找中位数的本质就是找数

那么找数的本质是什么呢?

就是排除不符合的呀!!

那怎么找才能更快呢??

当然是一次性排除的越多越好啦!!!

那么结合二分法,我们如果一次就能能排除一半就好啦!

虽然实际上我们并不能一次排除一半(天底下哪有那么香的事情呢?)

但是事情似乎有那么一点儿端倪了……

下面先说两个思路:

思路一:这里的中位数,本质上就是排在中间的数,其实就是找第K大的问题。

思路二:根据中位数两边的性质,中位数左右两边的数的个数相等,我们可以将数组从中间进行分割,保证左边的数都小于右边的数,这样我们就可以在分割线处找到中位数。

以上两种思路分别对应下面的解法一和解法二。

解法一 找第K大问题

首先看解法一,这里K是什么?

int m = nums1.length;
int n = nums2.length;
int len = m + n;//两个数组的总长度

当len为奇数时,K = len / 2 + 1;
当len为偶数时,我们应该计算中间两个数的平均值,中间两个数分别为Kleft = len / 2, Kright = len / 2 + 1;

这里我们希望将奇数和偶数进行合并,可以将奇数的中位数变成两个相等的数,即K = Kleft = Kright。
由于整数的除法是向下取整:

  1. len = 奇数时,以5为例,我们要找的是第三个数:
5>>1 = 2;
(5+1)>>1 = 3;
(5+2)>>1 = 3;
  1. len=偶数时,以6为例,我们要找的是第3和第4个数:
6>>1 = 3;
(6+1)>>1 = 3;
(6+2)>>1 = 4;

所以,我们可以这样合并两种情况:

Kleft = (len+1)>>1;
Kright = (len+2)>>1;

那么接下来的问题就是:
如果使用二分法找第K个数应该怎么找呢?

大致思路是:先找两个数组中的第K/2个数,将两数进行比较,由于数组是有序的,所以较小的第K/2个数一定不是符合要求的数,我们可以排除出去,然后再在剩下的数中找第K-K/2个数。

具体解法看下图:
在这里插入图片描述
由此我们可以得到:
通过排除前面的K/2个数,在剩下的新数组中找第K-K/2个数,如此递归,当K=1时递归结束,返回当前数组的最小值。

这样我们就可以分别找到Kleft和Kright的值,计算题目之间的平均值,就是我们要找的中位数。

相信到这里你已经知道怎么解题啦!

上代码!!!

class Solution {
   

    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
   
        int m = nums1.length;
        int n = nums2.length;
        int left = (m+n+1)>>1;
        int right = (m+n+2)>>1;
        return (findkth(nums1,0,nums2,0
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值