【LeetCode】寻找两个有序数组的中位数【性质分析+二分】
给定两个大小为 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
分析:

m为数组A元素数量
n为数组B元素数量
通过上图我们可以得知:
1.在合并后的大数组中,中位数的作用就是把数组分成元素数量相同的两部分,这两部分的元素是连续的,并且右侧的元素大于等于或者左侧的元素(也就是橙色元素大于或者等于绿色元素)
2.大数组中的元素不是来自于数组A就是来自于数组B,也就是说,数组A和数组B肯定是由分割线两侧的元素混合构成的(先不考虑特殊情况),由于他们都是有序数组,那么数组A和数组B中肯定也存在两条这样的分割线i和j,我们只需要在A数组和B数组中找到确切的i分割线和j分割线的位置,就可以确定大数组中分割线的位置,从而就可以确定中位数的位置
3.那么怎么寻找合适的i和j呢?
i和j满足的要求:i+j=(n+m+1)/2 (+1是为了保证元素总数量无论是奇数还是偶数该公式都成立)
根据公式知道,i和j只要确定了一个,另外一个也就确定了,所以我们只需要在数组A中寻找合适的i,那什么样的i才是合适的i呢?
合适的i和j必须要满足以下要求:
1)A[i]>=B[j-1]
2)B[j]>=A[i-1]
也就是保证所有橙色元素都大于或者等于绿色元素,换句话说就是为了保证大数组中右侧元素都大于或者等于左侧元素,只有这样的i和j才是合适的,才可以根据i和j确定大数组中位数的位置
那么当i和j不合适时,我们应该怎么调整呢?我们调整i,j也会随着变化,所有我只对i进行调整就好
当A[i]<B[j-1]时:说明i太小了,i应该右移
当B[j]<A[i-1]时:说明i太大了,i应该左移
我们可以通过二分的方式来移动i
当找到合适的i和j后
如果总元素数量为奇数,那么左侧最大元素max(A[i-1],B[j-1])就是中位数
如果总元素数量为偶数,那么左侧最大元素和右侧最小元素的平均值就是中位数
ps:右侧最小元素=min(A[i],B[j])
需要处理几种特殊情况:
1)如果B元素数量比A元素数量少的话,通过i得到的j值在数组B中可能会越界
解决方案:如果数组A的元素数量比数组B的元素数量多,那么交换A,B数组的元素,也就是说,i是在数组元素数量少的数组上移动的,这样通过i得到的j值在B数组肯定不会越界
2)i等于0的情况
这种情况下,i-1会越界,那么左侧的最大元素为B[j-1]就好
3)j等于0的情况
这种情况下,j-1会越界,那么左侧的最大元素为A[i-1]就好
4)i等于m的情况
这种情况下,A[m]元素取不到,也越界了,那么右侧最小元素为B[j]就好
5)j等于n的情况
这种情况下,B[j]元素取不到,也越界了,那么右侧最小元素为A[i]就好
时间复杂度分析:对A数组进行二分寻找合适的i,又因为A数组是元素数量最少的数组,所以该算法的时间复杂度为:O(log (min(m,n)))
空间复杂度:O(1)
另外一篇也很不错的博文:https://mp.weixin.qq.com/s/OE4lHO8-jOIxIfWO_1oNpQ
code:
double findMedianSortedArrays(vector<int>& A, vector<int>& B)
{
int m=A.size();
int n=B.size();
if(m>n)//i指向A数组,A为短数组可以避免j越界
{
swap(A,B);
swap(n,m);
}
int low=;
int high=m;
int k=(m+n+)/;
while(low<=high)//二分A数组
{
int i=(low+high)/;//i指向A数组
int j=k-i;//j指向B数组
if(i<high&&A[i]<B[j-])//i太小,i需要右移
{
low=i+;
}else if(i>low&&A[i-]>B[j])//i太大,i需要左移
{
high=i-;
}else//找到了合格的i,j
{
int maxleft;
//特殊情况
if(i==)
{
maxleft=B[j-];
}else if(j==)
{
maxleft=A[i-];
}else
{
maxleft=max(A[i-],B[j-]);//获得左侧最大值
}
if((m+n)%==)//如果两个数组的元素数量为奇数,那么左侧的最大值就是中位数
return maxleft*1.0;
int minright;
//特殊情况
if(i==m)
{
minright=B[j];
}else if(j==n)
{
minright=A[i];
}else
{
minright=min(A[i],B[j]);//获得右侧最小值
}
return (maxleft+minright)/2.0;//元素总数量为偶数,那么中位数等于左侧最大值和右侧最小值的平均值
}
}
return 0.0;
}
另外一种时间复杂度稍微差点的方法
将求中位数转化为求第k大数,当k=(m+n+1)/2时,为原问题的解,那么怎么求两个数组的第k大数呢?
分别求出A数组和B数组的第k/2个数x和y,然后比较x,y
当x<y时,说明第k个数位于A数组的第k/2个数的后半段
当x>y时,说明第k个数位于B数组的第k/2个数的前半段
问题规模缩小了一般,然后递归处理就行了(特殊情况的细节没有说明,这里只讲解一下大概思路,因为该方法时间复杂度较高,为O(log(m+n))
【LeetCode】寻找两个有序数组的中位数【性质分析+二分】的更多相关文章
- leetcode -- 寻找两个有序数组的中位数
题目: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nu ...
- LeetCode寻找两个有序数组的中位数
题目: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nu ...
- LeetCode Golang 4. 寻找两个有序数组的中位数
4. 寻找两个有序数组的中位数 很明显我偷了懒, 没有给出正确的算法,因为官方的解法需要时间仔细看一下... func findMedianSortedArrays(nums1 []int, nums ...
- Leetcode(4)寻找两个有序数组的中位数
Leetcode(4)寻找两个有序数组的中位数 [题目表述]: 给定两个大小为 m 和 n 的有序数组 nums1 和* nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O( ...
- Java实现 LeetCode 4 寻找两个有序数组的中位数
寻找两个有序数组的中位数 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 n ...
- 0004. 寻找两个有序数组的中位数(Java)
4. 寻找两个有序数组的中位数 https://leetcode-cn.com/problems/median-of-two-sorted-arrays/ 最简单的就是用最简单的,把两个数组分别抽出然 ...
- leetcode题目4.寻找两个有序数组的中位数(困难)
题目描述: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 ...
- leetcode刷题四<寻找两个有序数组的中位数>
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2 ...
- [LeetCode] 4. 寻找两个有序数组的中位数
题目链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/ 题目描述: 给定两个大小为 m 和 n 的有序数组 nums1 和 ...
随机推荐
- JavaScript基础04——数组的创建及方法
数组的概念及定义 数组的概念: 一组数据,数据的组和 哪些数据的组和,只要是数据(所有数据),就可以放在数组中 数组的意义: 可以同时操作多个数据 数组 ...
- zeebe 0.20.0 发布生产可用了!
一个比较好消息,来自camunda zeebe 团队的消息,zeebe 0.20.0 发布,终于可以生产可用了 如果关注了官方的声明的话,同时团队也出了一个自己的许可协议,但是和大部分当前的开源 产品 ...
- [THUPC2019]不等式/[51Nod1598]方程最小值
[THUPC2019]不等式/[51Nod1598]方程最小值 题目大意: 给定\(a_{1\sim n}\)和\(b_{1\sim n}\),令\(f_k(x)=\sum_{i=1}^k|a_ix+ ...
- GUI引发的一场脑部大战|wine、wsl、mono、gtk、qt
没写完不想写了,先发布吧,这就是一个引子. 在春天种下一颗种子---- GUI引发的一场脑部大战|wine.wsl.mono.gtk.qt 思路开拓了,方法一下子就来了 wine可以运行大部分Wind ...
- Oracle in不超过1000,List<String>参数拆分,代码举例
public Map<String,Map<String, Object>> getConsInfo(List<String> consIdList) { Map& ...
- K8S从入门到放弃
K8S介绍相关 kubernetes(K8S)集群及Dashboard安装配置 kubernetes(K8S)创建自签TLS证书 K8S Kubernetes 架构 K8S组件 K8S API对象 K ...
- openstackx
- Nacos学习
Nacos是阿里开源的一个新框架,在分布式的架构中,Nacos同时扮演着服务注册中心和配置中心的角色.今天主要讲的是Nacos作为服务注册中心. 分布式中著名的CAP理论,任何一种服务注册中心都只能实 ...
- tensorflow运行时openssl与boringssl兼容性问题
tensorflow中,grpc使用boringssl进行加密,boringssl是google基于openssl自行开发的一条分支,有许多相同函数,但底层实现以及支持的加密类型有不同. 且tenso ...
- 关于qemu的二三事(1)————qemu的特殊参数之monitor
qemu作为一个十分重要的虚拟化工具,提供了丰富的功能/参数来支持虚拟化的各种操作. 下面仅就monitor这个参数或者说是功能来结合自己的实际体验来做个简要介绍. 如何进入qemu的monitor模 ...
