LeetCode 4 - 两个排序数组的中位数 - [分治]
题目链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/description/
给定两个大小为 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$ 小数,
不妨先假设两个有序数组的长度都是大于等于 $c = \left\lfloor {\frac{k}{2}} \right\rfloor$ 的,比较 $A[c]$ 和 $B[c]$,有两种情况:
1、$A[c] \le B[c]$,那么两个数组合并之后,若 $B[1] \sim B[c]$ 的位置越往前靠,相应的 $A[c]$ 就越会往后靠,但显然 $B[c]$ 所在位置的最靠前情况是在第 $2c \le k$ 个,那么 $A[c]$ 所在位置的最差情况就是在第 $2c-1 \le k-1$ 个,因此 $A[1] \sim A[c]$ 必然在前 $k-1$ 小的数之中,可以将 $A[1] \sim A[c]$ 截去,不影响寻找第 $k$ 小数;
2、$A[c] > B[c]$,类似于情况2,可以将 $B[1] \sim B[c]$ 截去。
若两个有序数组的长度存在小于 $c = \left\lfloor {\frac{k}{2}} \right\rfloor$ 的情况呢?首先可以确定的是,就算存在这种情况,也肯定只有其中一个的长度会小于 $c$,
不妨设是 $A$ 数组的长度小于 $c$,那么,可以比较 $A[A.size]$ 和 $B[k-A.size]$,和上面也是一样的道理。
最后处理边界情况:当 $k=1$ 的时候,返回 $A[1]$ 和 $B[1]$ 中小的那一个即可;当两个数组中有一个为空的时候,就返回另一个数组的第 $k$ 个元素。
时间复杂度:
考虑是不断地让 $k$ 除以 $2$,直到 $k=1$ 时停止,故时间复杂度 $O(\log(k)) = O(\log(len)) = O(\log(m+n))$,满足题目要求。
AC代码:
class Solution
{
public:
int getkth(const vector<int>& nums1,int x,const vector<int>& nums2,int y,int k)
{
if(x>=nums1.size()) return nums2[y+k-]; //A数组为空
if(y>=nums2.size()) return nums1[x+k-]; //B数组为空
if(k==) return min(nums1[x],nums2[y]); int c1=min((int)nums1.size()-x,k/);
int c2=min((int)nums2.size()-y,k/);
if(nums1[x+c1-]<=nums2[y+c2-]) return getkth(nums1,x+c1,nums2,y,k-c1);
else return getkth(nums1,x,nums2,y+c2,k-c2);
}
double findMedianSortedArrays(vector<int>& nums1,vector<int>& nums2)
{
int len=nums1.size()+nums2.size();
if(len%) return getkth(nums1,,nums2,,(len+)/);
else return (getkth(nums1,,nums2,,len/)+getkth(nums1,,nums2,,len/+))/2.0;
}
};
这道题目,最令人震惊的是……
我新开一个vector把nums1和nums2的元素都扔进去然后sort了一下,$O(1)$ 输出中位数,明明 $O((m+n) \log(m+n))$ 的时间复杂度,居然和 $O(\log(m+n))$ 跑的一样快,都是52ms……
感觉自己搞了假的时间复杂度……
所以我开始怀疑,是不是LeetCode用了很水数据,实际上大部分时间是在其他什么地方耗费的,果然,关闭IO同步之后可以 16ms 内跑完:
static const auto io_sync_off = []()
{
// turn off sync
std::ios::sync_with_stdio(false);
// untie in/out streams
std::cin.tie(nullptr);
return nullptr;
}();
class Solution
{
public:
inline int getkth(const vector<int>& nums1,int x,const vector<int>& nums2,int y,int k)
{
if(x>=nums1.size()) return nums2[y+k-]; //A数组为空
if(y>=nums2.size()) return nums1[x+k-]; //B数组为空
if(k==) return min(nums1[x],nums2[y]); int c1=min((int)nums1.size()-x,k/);
int c2=min((int)nums2.size()-y,k/);
if(nums1[x+c1-]<=nums2[y+c2-]) return getkth(nums1,x+c1,nums2,y,k-c1);
else return getkth(nums1,x,nums2,y+c2,k-c2);
}
double findMedianSortedArrays(vector<int>& nums1,vector<int>& nums2)
{
int len=nums1.size()+nums2.size();
if(len%) return getkth(nums1,,nums2,,(len+)/);
else return (getkth(nums1,,nums2,,len/)+getkth(nums1,,nums2,,len/+))/2.0;
}
};
我还同样把上面 $O((m+n) \log(m+n))$ 的那个算法关了IO同步试了一下,耗时 32ms……这个 16ms 的差距,应该即使优化复杂度的结果了吧,还算有个安慰。
LeetCode 4 - 两个排序数组的中位数 - [分治]的更多相关文章
- LeetCode#5 两个排序数组的中位数
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . 请找出这两个有序数组的中位数.要求算法的时间复杂度为 O(log (m+n)) . 你可以假设 nums1 和 nums2 ...
- leetcode 4.两个排序数组的中位数
题目: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . 请找出这两个有序数组的中位数.要求算法的时间复杂度为 O(log (m+n)) . 你可以假设 nums1 和 nums ...
- leetcode,两个排序数组的中位数
先上题目描述: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . 请找出这两个有序数组的中位数.要求算法的时间复杂度为 O(log (m+n)) . 你可以假设 nums1 和 ...
- leetcode python两个排序数组的中位数
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . 请找出这两个有序数组的中位数.要求算法的时间复杂度为 O(log (m+n)) . 你可以假设 nums1 和 nums2 不同 ...
- LeetCode(4):两个排序数组的中位数
Hard! 题目描述: 有两个大小为 m 和 n 的排序数组 nums1 和 nums2 . 请找出两个排序数组的中位数并且总的运行时间复杂度为 O(log (m+n)) . 示例 1: nums1 ...
- LeetCode4. 两个排序数组的中位数
4. 两个排序数组的中位数 问题描述 There are two sorted arrays nums1 and nums2 of size m and n respectively.Find the ...
- 2.Median of Two Sorted Arrays (两个排序数组的中位数)
要求:Median of Two Sorted Arrays (求两个排序数组的中位数) 分析:1. 两个数组含有的数字总数为偶数或奇数两种情况.2. 有数组可能为空. 解决方法: 1.排序法 时间复 ...
- LeetCode-4. 两个排序数组的中位数(详解)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/description/ 有两个大小为 m 和 n 的排序数组 nums ...
- JavaScript实现获取两个排序数组的中位数算法示例
本文实例讲述了JavaScript排序代码实现获取两个排序数组的中位数算法.分享给大家供大家参考,具体如下: 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . 请找出这两个 ...
随机推荐
- 关于input时间框设置了弹出选择就不能手动输入的控制
<input class="Wdate" onclick="WdatePicker({minDate:'#F{$dp.$D(\'startDate\');}',ma ...
- (转)超过 130 个你需要了解的 vim 命令
从 1970 年开始,vi 和 vim 就成为了程序员最喜爱的文本编辑器之一.5 年前,我写了一个问自己名为 “每个程序员都应该知道的 100 个 vim 命令” 这次算是之前那篇文章的改进版,希望你 ...
- JDK自带JVM性能调优监控工具jps、jstack、jmap、jhat、jstat
原文地址:https://www.jianshu.com/p/db954cb968fb JVM性能调优监控工具jps.jstack.jmap.jhat.jstat位于JDK的bin目录,这些工具短小精 ...
- Mac MySQL 数据库配置(关系型数据库管理系统)
前言 MySQL 关系型数据库管理系统. 1.配置准备工作 1)配置数据库准备工作 下载相关软件 mysql-5.7.21-1-macos10.13-x86_64.dmg mysql-workbenc ...
- NDK配置
NDK 配置 Android SDK中下载NDK, LLDB Android.mk 和 Application.mk 简单来说 Android.mk 用来描述需要生成哪些模块的 .so 文件 Appl ...
- JVM源码分析之Object.wait/notify实现(转载)
最简单的东西,往往包含了最复杂的实现,因为需要为上层的存在提供一个稳定的基础,Object作为java中所有对象的基类,其存在的价值不言而喻,其中wait和notify方法的实现多线程协作提供了保证. ...
- aaronyang的百度地图API之LBS云与.NET开发 Javascript API 2.0【把数据存到LBS云2/2】
中国的IT 需要无私分享和贡献的人,一起努力 本篇博客来自地址:http://www.cnblogs.com/AaronYang/p/3672898.html,请支持原创,未经允许不许转载 1.新建一 ...
- 初识HTTPS
初识HTTPS HTTPS也被叫做“基于TLS的HTTP,基于SSL的HTTP,HTTP安全“,它是一个在Internet上广泛使用的计算机网络安全通信协议. 即HTTPS是HTTP的安全版本,在了解 ...
- Git应用实践(二)
[时间:2017-08] [状态:Open] [关键词:Git,git diff, git apply, git format-patch, git am, git log] 0-背景 距上次总结Gi ...
- Selenium Web 自动化 - 项目实战环境准备
Selenium Web 自动化 - 项目实战环境准备 2016-08-29 目录 1 部署TestNG 1.1 安装TestNG 1.2 添加TestNG类库2 部署Maven 2.1 mav ...