[leetcode] 4 寻找两个有序数组的中位数(二分+递归查找第K小数)(重要)
问题描述
给定两个大小为 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小数)(重要)相关推荐
- 【LeetCode】寻找两个有序数组的中位数【性质分析+二分】
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 nums2 ...
- leetcode 4. 寻找两个有序数组的中位数,c语言
leetcode上第四道题,如下. 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2.请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)).你可以假 ...
- LeetCode 4. 寻找两个有序数组的中位数(二分查找,难)
文章目录 1. 题目 2. 解题 2.1 合并数组 2.2 优化2.1解法,双指针 2.3 二分法(找第k个数) 2.4 切分法 1. 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 n ...
- Leetcode(4)寻找两个有序数组的中位数
题目描述 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 n ...
- LeetCode 4.寻找两个有序数组的中位数
题目描述 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 n ...
- leetcode 4 --- 寻找两个有序数组的中位数
1 题目 给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组的中位数. 进阶:设计一个时间复杂度为 O(log (m+n)) 的算法. 2 解 ...
- [leetcode] 4. 寻找两个有序数组的中位数
官方题解:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xun-zhao-liang-ge-you-xu- ...
- 20191016:(leetcode习题)寻找两个有序数组的中位数
寻找两个有序数组的中位数 题目 大致思路 代码实现 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log( ...
- LeetCode(Python实现)—寻找两个有序数组的中位数
4.寻找两个有序数组的中位数 题目大意 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). ...
最新文章
- 深度学习各种环境问题积累
- C++知识点32——使用C++标准库(关联容器set和multiset的初始化,赋值,查找,添加,删除与迭代器失效)
- 计算机的几种类型单词、快捷键
- 解决: AOSP 编译AndroidQ preview 失败
- KVM中Virtio网络的演化之路
- 服务器lIS绑定网站,DataList 中动态绑定服务器子控件的代码
- 个人笔记:ORACLE大页内存hugepage和SGA、PGA的经验,SGA并不是越大越好
- OpenStack三种类型的NAT转换
- php编辑工具绿色,php编写软件下载|
- cout 格式化输出
- 40. MySQL的权限与安全
- 计算机取消补考,2005级《计算机文化基础》补考通知
- php漏洞 代码,PHP漏洞代码点滴
- 递归回溯法求数独全部解
- ArrayList集合的使用
- C#练习题答案: TO DE-RY-PO-陆琪暗号【难度:1级】--景越C#经典编程题库,1000道C#基础练习题等你来挑战
- 如何删除映射网络驱动器
- 前端的小玩意(9.5)——做一个仿360工具箱的web页面(完结篇,可以跑起来的工具箱)
- 发现的一款很有个性的时钟插件
- 014.西门子PLC与变频器USS通讯
热门文章
- 软件自动化测试平台设计,软件自动测试平台的设计与实现
- 物联lot是什么意思_新一代基于物联网NB-loT技术的智能共享单车解决
- Treats for the Cows
- 手写字体识别 --MNIST数据集
- 灵眸action_大疆 Osmo Action 灵眸运动相机评测:GoPro 终于有了像样的对手
- 全球经济大萧条,春风沐浴网上店
- Vue-Router的push和replace方法[Uncaught (in promise) Error]解决方案
- 广东省江门市谷歌卫星地图下载
- SVM详解(三)支持向量机使用核技巧
- 华为:研发协同,为什么说效率是第一重要的事儿?