题目链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/description/

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。

请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。

你可以假设 nums1 和 nums2 不同时为空。

示例 1:

  1. nums1 = [1, 3]
  2. nums2 = [2]
  3.  
  4. 中位数是 2.0

示例 2:

  1. nums1 = [1, 2]
  2. nums2 = [3, 4]
  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代码:

  1. class Solution
  2. {
  3. public:
  4. int getkth(const vector<int>& nums1,int x,const vector<int>& nums2,int y,int k)
  5. {
  6. if(x>=nums1.size()) return nums2[y+k-]; //A数组为空
  7. if(y>=nums2.size()) return nums1[x+k-]; //B数组为空
  8. if(k==) return min(nums1[x],nums2[y]);
  9.  
  10. int c1=min((int)nums1.size()-x,k/);
  11. int c2=min((int)nums2.size()-y,k/);
  12. if(nums1[x+c1-]<=nums2[y+c2-]) return getkth(nums1,x+c1,nums2,y,k-c1);
  13. else return getkth(nums1,x,nums2,y+c2,k-c2);
  14. }
  15. double findMedianSortedArrays(vector<int>& nums1,vector<int>& nums2)
  16. {
  17. int len=nums1.size()+nums2.size();
  18. if(len%) return getkth(nums1,,nums2,,(len+)/);
  19. else return (getkth(nums1,,nums2,,len/)+getkth(nums1,,nums2,,len/+))/2.0;
  20. }
  21. };

这道题目,最令人震惊的是……

我新开一个vector把nums1和nums2的元素都扔进去然后sort了一下,$O(1)$ 输出中位数,明明 $O((m+n) \log(m+n))$ 的时间复杂度,居然和 $O(\log(m+n))$ 跑的一样快,都是52ms……

感觉自己搞了假的时间复杂度……

所以我开始怀疑,是不是LeetCode用了很水数据,实际上大部分时间是在其他什么地方耗费的,果然,关闭IO同步之后可以 16ms 内跑完:

  1. static const auto io_sync_off = []()
  2. {
  3. // turn off sync
  4. std::ios::sync_with_stdio(false);
  5. // untie in/out streams
  6. std::cin.tie(nullptr);
  7. return nullptr;
  8. }();
  9. class Solution
  10. {
  11. public:
  12. inline int getkth(const vector<int>& nums1,int x,const vector<int>& nums2,int y,int k)
  13. {
  14. if(x>=nums1.size()) return nums2[y+k-]; //A数组为空
  15. if(y>=nums2.size()) return nums1[x+k-]; //B数组为空
  16. if(k==) return min(nums1[x],nums2[y]);
  17.  
  18. int c1=min((int)nums1.size()-x,k/);
  19. int c2=min((int)nums2.size()-y,k/);
  20. if(nums1[x+c1-]<=nums2[y+c2-]) return getkth(nums1,x+c1,nums2,y,k-c1);
  21. else return getkth(nums1,x,nums2,y+c2,k-c2);
  22. }
  23. double findMedianSortedArrays(vector<int>& nums1,vector<int>& nums2)
  24. {
  25. int len=nums1.size()+nums2.size();
  26. if(len%) return getkth(nums1,,nums2,,(len+)/);
  27. else return (getkth(nums1,,nums2,,len/)+getkth(nums1,,nums2,,len/+))/2.0;
  28. }
  29. };

我还同样把上面 $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. php static 变量的例子

    class test { public static function a(){} public function b(){} } $obj = new test; 调用 代码 test::a(); ...

  2. sonarqube 自动代码审查

    1.docker 拉取sonarqube docker pull sonarqube 2.启动docker docker run -d --name sonarqube -p 9000:9000 so ...

  3. mariadb(MySql)设置远程访问权限

    [问题]mariadb(MySql)安装之后,本地连接mysql是可以的,但是远程的机器不能连接和访问. [解决]修改mysql远程连接的ip限制配置. [步骤]1.本地mysql客户端连接mysql ...

  4. [docker]macvlan实现双vlan互通

    关于vlan的冷知识 vlan范围:0~4095 0,4095 保留 仅限系统使用 用户不能查看和使用这些VLAN 1 正常 Cisco默认VLAN 用户能够使用该VLAN,但不能删除它 2-1001 ...

  5. Android studio的主题颜色修改

    1.选择喜欢的主题 http://color-themes.com/?view=index 好几十款,总有一款你喜欢 2.下载你喜欢的主题,注意是jar文件 .File -> Import Se ...

  6. 《深入应用C++11:代码优化与工程级应用》勘误表

    <深入应用C++11:代码优化与工程级应用>勘误表,会不断更新,欢迎读者留言或发邮件(cpp11book@163.com)给我提出宝贵意见. 1.第7.3节目录final和override ...

  7. Java和Scala语法比较

    类型推断 挑逗指数: 四星 我们知道,Scala一向以强大的类型推断闻名于世.很多时候,我们无须关心Scala类型推断系统的存在,因为很多时候它推断的结果跟直觉是一致的. Java在2016 年也新增 ...

  8. Apache Hadoop YARN: 背景及概述

    从2012年8月开始Apache Hadoop YARN(YARN = Yet Another Resource Negotiator)成了Apache Hadoop的一项子工程.自此Apache H ...

  9. maven安装及与eclipse集成

    一.maven安装 1,下载地址:http://maven.apache.org/download.cgi 2,解压maven到:C:\Java\apache-maven-3.5.3,目录可以随意. ...

  10. 【转】Winform程序未捕获异常解决方法 EventType clr20r3 P1

    from:http://blog.csdn.net/chichaodechao/article/details/8294922 在开发winform程序时,用到多线程,在服务器部署后运行,老是自动关才 ...