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 . 请找出这两个 ...
随机推荐
- unix缓冲
目的:尽量减少read,write调用的次数. 标准IO提供3种IO: 1.全缓冲.在填满IO缓冲区后才进行实际的IO操作. 2.行缓冲.当输入和输出遇到换行符时,执行IO操作.(设计终端) 3.不带 ...
- C#中回滚TransactionScope的使用方法和原理
TransactionScope只要一个操作失败,它会自动回滚,Complete表示事务完成 实事上,一个错误的理解就是Complete()方法是提交事务的,这是错误的,事实上,它的作用的表示本事 ...
- [转]linux(ubuntu)上运行网易popo
popo没有linux版,连web版和android版都没有,这个实在是不方便.搞了很久,终于搞定了ubuntu上运行popo,暂时还没出现什么问题. 首先要安装PlayOnLinux,直接安装win ...
- hexo + Github Page 0元建立博客攻略
传送门: 5分钟 0元搭建个人独立博客网站(一):https://mp.weixin.qq.com/s/69isJE191WV2gaVbjrwTtw 5分钟 0元搭建个人独立博客网站(二):https ...
- layui table 根据条件改变更换表格颜色 高亮显示 数据筛选
请问想让当layui表格的某个字段符合某个条件的时候,让该行变颜色.这样可以实现么. layui数据表格怎么更换表格颜色 layui表格 通过判断某一行中的某一列的值进行设置这一行的颜色 LayUI之 ...
- 【原】使用Tkinter绘制GUI并结合Matplotlib实现交互式绘图
在数据分析的过程中,往往需要对所建立的模型进行可视化,并调整其中的某些参数. 通常情况下,在Python中可以通过Matplotlib来进行绘制图像.然而该绘制过程是静态的,也就是每次调整完参数需要重 ...
- python中的列表、元组、数组——是不是特别容易混淆啊??
列表: 1. 即list, 是python内置的数据类型. 它的形式是: a = [1, 2, 3, 4, 5] 2. 列表内的值是可以改变的: 即可以这样子: a[0] = 100, 把列表的 ...
- react-router 4.3 js实现跳转
import React, {Component} from 'react'; import { NavLink,Link } from "react-router-dom"; i ...
- CentOS7 设置软件镜像源
Linux拥有众多的发行版,每个发行版都有提供镜像,但是,在国内这些镜像的下载速度参差不齐,偶尔会有更新失败的情况. 网上众多推荐的镜像源为163的镜像,笔者通过一段时间的试用,发现某些小众带宽访问1 ...
- ios开发之--valueForKeyPath的用法
1.获取数组中的平均值,最大值,最小值,总和,代码如下: NSArray *ary = @[@,@,@,@,@,@,@]; [self caculateArray:ary]; -(NSString * ...