给定两个大小为 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=0;int high=m;int k=(m+n+1)/2;while(low<=high)//二分A数组
    {int i=(low+high)/2;//i指向A数组int j=k-i;//j指向B数组if(i<high&&A[i]<B[j-1])//i太小,i需要右移
        {low=i+1;}else if(i>low&&A[i-1]>B[j])//i太大,i需要左移
        {high=i-1;}else//找到了合格的i,j
        {int maxleft;//特殊情况if(i==0){maxleft=B[j-1];}else if(j==0){maxleft=A[i-1];}else{maxleft=max(A[i-1],B[j-1]);//获得左侧最大值
            }if((m+n)%2==1)//如果两个数组的元素数量为奇数,那么左侧的最大值就是中位数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))

具体请参考:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/zhen-zheng-ologmnde-jie-fa-na-xie-shuo-gui-bing-pa/

 

 

转载于:https://www.cnblogs.com/yinbiao/p/11278881.html

【LeetCode】寻找两个有序数组的中位数【性质分析+二分】相关推荐

  1. LeetCode——寻找两个有序数组的中位数

    题目: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nu ...

  2. leetcode 寻找两个有序数组的中位数 hard

    题目链接 这篇文章写得很全面:https://www.cnblogs.com/grandyang/p/4465932.html 摘抄如下: 这道题让我们求两个有序数组的中位数,而且限制了时间复杂度为O ...

  3. leetcode 寻找两个有序数组的中位数

    2085 / 2085 个通过测试用例 状态:通过 执行用时:4 ms 内存消耗:47.6 MB 提交时间:6 月,4 周之前 class Solution {public double findMe ...

  4. 20191016:(leetcode习题)寻找两个有序数组的中位数

    寻找两个有序数组的中位数 题目 大致思路 代码实现 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log( ...

  5. LeetCode(Python实现)—寻找两个有序数组的中位数

    4.寻找两个有序数组的中位数 题目大意 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). ...

  6. 算法--------------------寻找两个有序数组的中位数

    题目描述 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2.请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)).你可以假设 nums1 和 num ...

  7. Python寻找两个有序数组的中位数

    Python寻找两个有序数组的中位数 审题: 找出意味着这是一个查找算法题 算法复杂度log级别,就是提示你是二分查找 二分查找实现一般为递归 (1)递归包括递归体 (2)终止条件 思路: 定理: 有 ...

  8. 两个有序数组的中位数 python_Python寻找两个有序数组的中位数实例详解

    Python寻找两个有序数组的中位数 审题: 1.找出意味着这是一个查找算法题 2.算法复杂度log级别,就是提示你是二分查找 3.二分查找实现一般为递归 (1)递归包括递归体 (2)终止条件 思路: ...

  9. LeetCode4. 寻找两个有序数组的中位数

    4. 寻找两个有序数组的中位数 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假 ...

  10. (JS)寻找两个有序数组的中位数

    寻找两个有序数组的中位数 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 n ...

最新文章

  1. c语言ascw,Asc/AscB/AscW和Chr/ChrB/ChrW函数之间的区别
  2. 建博客的原因。。。。
  3. 关于 use-default-filters 属性的说明
  4. ByteArrayOutputStream
  5. 编程名言(有些趣味性)
  6. Objective -C Memory Management 内存管理 第一部分
  7. 转载:成功应用ERP的思路和方法分析
  8. [react] 怎么在JSX里使用自定义属性?
  9. LinkedList的实现原理
  10. 运算符重载——关系运算符重载
  11. Linux防火墙-iptables
  12. [文摘20100706】软件架构师应该知道的97件事
  13. pdf电脑地址转网络地址.txt
  14. 2台电脑一根网线传文件_安卓端和Mac快速连接传文件
  15. linux命令、vi编辑器常用命令
  16. 关于virtual box安装windows xp虚拟机遇到的一个问题
  17. HCNA培训常见问题001-HCNA AI学习什么内容?
  18. Python数据可视化三部曲之 Pyecharts 从上手到上头
  19. SOFARPC —— SPI 解析
  20. 非接触借记贷记流程报文解析

热门文章

  1. python支持复数以及相关的运算吗_Python复数属性和方法运算操作示例
  2. python中pprint是干什么的_Python中的pprint折腾记
  3. node.js学习文档_学习NodeJs从每天一个小知识点开始
  4. python语言输入中文_selenium+python 语言编写问题,在执行时无法输入中文用户名...
  5. python random函数shuffle_Python|有趣的shuffle方法
  6. C++ 偏微分数值计算库_ESYSim仿真器介绍之一 C++库介绍
  7. echars vue 添加数据没更新_vue在使用ECharts时的异步更新和数据加载详解
  8. sql取整数_SQL 窗口函数
  9. 目标检测(二十三)--DenseBox
  10. 2015-FCN论文解读