题目链接: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 - 两个排序数组的中位数 - [分治]的更多相关文章

  1. LeetCode#5 两个排序数组的中位数

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

  2. leetcode 4.两个排序数组的中位数

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

  3. leetcode,两个排序数组的中位数

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

  4. leetcode python两个排序数组的中位数

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

  5. LeetCode(4):两个排序数组的中位数

    Hard! 题目描述: 有两个大小为 m 和 n 的排序数组 nums1 和 nums2 . 请找出两个排序数组的中位数并且总的运行时间复杂度为 O(log (m+n)) . 示例 1: nums1 ...

  6. LeetCode4. 两个排序数组的中位数

    4. 两个排序数组的中位数 问题描述 There are two sorted arrays nums1 and nums2 of size m and n respectively.Find the ...

  7. 2.Median of Two Sorted Arrays (两个排序数组的中位数)

    要求:Median of Two Sorted Arrays (求两个排序数组的中位数) 分析:1. 两个数组含有的数字总数为偶数或奇数两种情况.2. 有数组可能为空. 解决方法: 1.排序法 时间复 ...

  8. LeetCode-4. 两个排序数组的中位数(详解)

    链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/description/ 有两个大小为 m 和 n 的排序数组 nums ...

  9. JavaScript实现获取两个排序数组的中位数算法示例

    本文实例讲述了JavaScript排序代码实现获取两个排序数组的中位数算法.分享给大家供大家参考,具体如下: 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . 请找出这两个 ...

随机推荐

  1. 关于input时间框设置了弹出选择就不能手动输入的控制

    <input class="Wdate" onclick="WdatePicker({minDate:'#F{$dp.$D(\'startDate\');}',ma ...

  2. (转)超过 130 个你需要了解的 vim 命令

    从 1970 年开始,vi 和 vim 就成为了程序员最喜爱的文本编辑器之一.5 年前,我写了一个问自己名为 “每个程序员都应该知道的 100 个 vim 命令” 这次算是之前那篇文章的改进版,希望你 ...

  3. JDK自带JVM性能调优监控工具jps、jstack、jmap、jhat、jstat

    原文地址:https://www.jianshu.com/p/db954cb968fb JVM性能调优监控工具jps.jstack.jmap.jhat.jstat位于JDK的bin目录,这些工具短小精 ...

  4. Mac MySQL 数据库配置(关系型数据库管理系统)

    前言 MySQL 关系型数据库管理系统. 1.配置准备工作 1)配置数据库准备工作 下载相关软件 mysql-5.7.21-1-macos10.13-x86_64.dmg mysql-workbenc ...

  5. NDK配置

    NDK 配置 Android SDK中下载NDK, LLDB Android.mk 和 Application.mk 简单来说 Android.mk 用来描述需要生成哪些模块的 .so 文件 Appl ...

  6. JVM源码分析之Object.wait/notify实现(转载)

    最简单的东西,往往包含了最复杂的实现,因为需要为上层的存在提供一个稳定的基础,Object作为java中所有对象的基类,其存在的价值不言而喻,其中wait和notify方法的实现多线程协作提供了保证. ...

  7. aaronyang的百度地图API之LBS云与.NET开发 Javascript API 2.0【把数据存到LBS云2/2】

    中国的IT 需要无私分享和贡献的人,一起努力 本篇博客来自地址:http://www.cnblogs.com/AaronYang/p/3672898.html,请支持原创,未经允许不许转载 1.新建一 ...

  8. 初识HTTPS

    初识HTTPS HTTPS也被叫做“基于TLS的HTTP,基于SSL的HTTP,HTTP安全“,它是一个在Internet上广泛使用的计算机网络安全通信协议. 即HTTPS是HTTP的安全版本,在了解 ...

  9. Git应用实践(二)

    [时间:2017-08] [状态:Open] [关键词:Git,git diff, git apply, git format-patch, git am, git log] 0-背景 距上次总结Gi ...

  10. Selenium Web 自动化 - 项目实战环境准备

    Selenium Web 自动化 - 项目实战环境准备 2016-08-29 目录 1 部署TestNG  1.1 安装TestNG  1.2 添加TestNG类库2 部署Maven  2.1 mav ...