问题描述

给定两个大小为 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

解题思路

看这个时间复杂度,应该是要进行二分求解,题意没有说清,应该是两个有序数组放在一起排序后的中位数。我们可以将其变得更加通用一些,转化为求两个有序数组的第K小数,要求时间复杂度O(log(m+n))。官方题解是二分求中位数,我们这里用递归来讲一下求第K小数。这里用的是二分的思想,但是是递归的模版。

假设第一个数组是a数组,长度是n,第二个数组是b数组,长度是m。假设下标从0开始,设x=K2−1x=\frac{K}{2}-1x=2K​−1,我们先从第一个数组中找到第K2\frac{K}{2}2K​个数为axa_xax​,第二个数组中找到第K2\frac{K}{2}2K​个数为bxb_xbx​。然后比较这两个数,如果ax<bxa_x<b_xax​<bx​,说明第K个数位于a数组的第K2\frac{K}{2}2K​个数的后半段,或者b数组中。

比如我们考虑两个数组:

a[1, 3, 6, 7]
b[2, 4, 8, 10, 13]

我们要找到的中位数是6,是第5个数,x=52−1x=\frac{5}{2}-1x=25​−1,首先第一步我们找到ax=3,bx=4a_x=3, b_x=4ax​=3,bx​=4,经过比较,发现ax<bxa_x<b_xax​<bx​,所以我们剩下的数组是(将小的那个a_x也扔掉):

a[6, 7]
b[2, 4, 8, 10, 13]

然后在这个里面搜第K−K2K- \frac{K}{2}K−2K​大元素,也就是第333大元素,此时x=32−1x=\frac{3}{2}-1x=23​−1,找到ax=6,bx=2a_x=6,b_x=2ax​=6,bx​=2,比较发现ax>bxa_x>b_xax​>bx​,所以我们剩下的数组是:

a[6, 7]
b[4, 8, 10, 13]

然后搜第3−3/2=23-3/2=23−3/2=2大元素,此时x=22−1x=\frac{2}{2}-1x=22​−1,找到ax=6,bx=4a_x=6, b_x=4ax​=6,bx​=4,比较发现ax>bxa_x>b_xax​>bx​,所以还剩下的是:

a[6, 7]
b[8, 10, 13]

此时应该找第1个元素,也就是两个数组首元素中最小的一个。因此最终答案就是6。

那为什么这样削呢?我们看下面这个图:

a和b是原数组,c是合并之后的数组,蓝线表示axa_xax​,红线表示bxb_xbx​,那么我们看c中,蓝线前面必定少于K个元素(因为ax<bxa_x<b_xax​<bx​,同时这两个都是第K2\frac{K}{2}2K​个元素,所以二者前面(包含二者)总共有K个元素(如果K为奇数就是K-1个元素)),所以说前面这部分就可以扔掉,直接去除了K2\frac{K}{2}2K​个数据。

还要考虑一种情况,就是你拿不到第K2\frac{K}{2}2K​个元素,就是某个数组太短了。这个时候我们就直接取最短的那个数组的最后一个元素,然后进行比较。如果这个更小,那么就将整个数组去掉,同时K-size()。

由于我们每次都是删除掉K2\frac{K}{2}2K​个元素,而K=n+m2K=\frac{n+m}{2}K=2n+m​,所以时间复杂度是O(log(m+n))的。同时空间复杂度也非常优秀,虽然我们用到了递归,但是这个递归属于尾递归,所以编译器不需要不停地堆栈,空间复杂度为 O(1)。

参考博客 https://leetcode.wang

完整代码

class Solution {public:int getKth(vector<int>& nums1, int start1, vector<int>& nums2, int start2, int k){int len1=nums1.size()-start1,len2=nums2.size()-start2;if(len1==0) return nums2[start2+k-1];//某个数组为空,直接返回另一个数组的第k个元素if(len2==0) return nums1[start1+k-1];if(k==1) return min(nums1[start1],nums2[start2]);//找第1个元素,直接找两个数组首个元素的最小值int k1=start1+min(len1,k/2)-1,k2=start2+min(len2,k/2)-1;//找到两个需要断的地方return nums1[k1]<nums2[k2] ? getKth(nums1,k1+1,nums2,start2,k-(k1-start1+1)):getKth(nums1,start1,nums2,k2+1,k-(k2-start2+1));}double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2){int n=nums1.size(),m=nums2.size();if((n+m)%2) return getKth(nums1,0,nums2,0,(n+m+1)/2);//如果是奇数,找到中位数else return (getKth(nums1,0,nums2,0,(n+m)/2)+getKth(nums1,0,nums2,0,(n+m+2)/2))*0.5;//偶数找到中间两个平均值}
};

[leetcode] 4 寻找两个有序数组的中位数(二分+递归查找第K小数)(重要)相关推荐

  1. 【LeetCode】寻找两个有序数组的中位数【性质分析+二分】

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

  2. leetcode 4. 寻找两个有序数组的中位数,c语言

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

  3. LeetCode 4. 寻找两个有序数组的中位数(二分查找,难)

    文章目录 1. 题目 2. 解题 2.1 合并数组 2.2 优化2.1解法,双指针 2.3 二分法(找第k个数) 2.4 切分法 1. 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 n ...

  4. Leetcode(4)寻找两个有序数组的中位数

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

  5. LeetCode 4.寻找两个有序数组的中位数

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

  6. leetcode 4 --- 寻找两个有序数组的中位数

    1 题目 给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组的中位数. 进阶:设计一个时间复杂度为 O(log (m+n)) 的算法. 2 解 ...

  7. [leetcode] 4. 寻找两个有序数组的中位数

    官方题解:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xun-zhao-liang-ge-you-xu- ...

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

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

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

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

最新文章

  1. 深度学习各种环境问题积累
  2. C++知识点32——使用C++标准库(关联容器set和multiset的初始化,赋值,查找,添加,删除与迭代器失效)
  3. 计算机的几种类型单词、快捷键
  4. 解决: AOSP 编译AndroidQ preview 失败
  5. KVM中Virtio网络的演化之路
  6. 服务器lIS绑定网站,DataList 中动态绑定服务器子控件的代码
  7. 个人笔记:ORACLE大页内存hugepage和SGA、PGA的经验,SGA并不是越大越好
  8. OpenStack三种类型的NAT转换
  9. php编辑工具绿色,php编写软件下载|
  10. cout 格式化输出
  11. 40. MySQL的权限与安全
  12. 计算机取消补考,2005级《计算机文化基础》补考通知
  13. php漏洞 代码,PHP漏洞代码点滴
  14. 递归回溯法求数独全部解
  15. ArrayList集合的使用
  16. C#练习题答案: TO DE-RY-PO-陆琪暗号【难度:1级】--景越C#经典编程题库,1000道C#基础练习题等你来挑战
  17. 如何删除映射网络驱动器
  18. 前端的小玩意(9.5)——做一个仿360工具箱的web页面(完结篇,可以跑起来的工具箱)
  19. 发现的一款很有个性的时钟插件
  20. 014.西门子PLC与变频器USS通讯

热门文章

  1. 软件自动化测试平台设计,软件自动测试平台的设计与实现
  2. 物联lot是什么意思_新一代基于物联网NB-loT技术的智能共享单车解决
  3. Treats for the Cows
  4. 手写字体识别 --MNIST数据集
  5. 灵眸action_大疆 Osmo Action 灵眸运动相机评测:GoPro 终于有了像样的对手
  6. 全球经济大萧条,春风沐浴网上店
  7. Vue-Router的push和replace方法[Uncaught (in promise) Error]解决方案
  8. 广东省江门市谷歌卫星地图下载
  9. SVM详解(三)支持向量机使用核技巧
  10. 华为:研发协同,为什么说效率是第一重要的事儿?