每天一道算法题目(18)——取等长有序数组的上中位数和不等长有序数组的第k小的数
1.取上中位数
题目:
给定两个有序数组arr1和arr2,两个数组长度都为N,求两个数组中所有数的上中位数。要求:时间复杂度O(logN)。
例如:
arr1 = {1,2,3,4};
arr2 = {3,4,5,6};
一共8个数则上中位数是第4个数,所以返回3。
arr1 = {0,1,2};
arr2 = {3,4,5};
一共6个数则上中位数是第3个数,所以返回2。
思路:
(1)假设两个数组长度为偶数,取中间节点index=1
1 2 3 4
1‘ 2’ 3‘ 4’
若2 == 2‘ ,则直接返回;
若2 > 2', 说明 2 至少排第4, 所以3,4可以排除,1’ 2‘(2’ 最多排第3)可以排除,所以对剩下的1 2和3‘ 4’ 递归
若2 < 2‘,同理递归1’ 2‘和3、4.
(2)假设两个数组长度为奇数,取中间节点index=2.
1 2 3 4 5
1‘ 2’ 3‘ 4’ 5’
若3 == 3‘ ,则直接返回;
若3 > 3', 说明 3 至少排第6, 所以4,5可以排除,1’ 2‘(2’ 最多排第4)可以排除,所以对剩下的1 2 3和 3‘ 4’ 5‘递归,其实3也能排除,但是为了保证两个数组的长度一样,保留3
若3 < 3‘,同理递归1’ 2‘ 3’和3、4 、5.
代码:
int getUpMedian(const vector<int> & arr1, int start1, int end1,const vector<int> & arr2, int start2, int end2) {
if(start1 == end1)
return min(arr1[start1], arr2[start2]);
int size = end1-start1+1;
int halfSize;
if(size&1 == 1)//奇
halfSize = (size + 1)/2;
else//偶
halfSize = size/2;
if(arr1[start1+halfSize - 1] == arr2[start2 + halfSize - 1])
return arr1[start1 + halfSize - 1];
else if(arr1[start1 + halfSize - 1] > arr2[start2 + halfSize - 1])
return getUpMedian(arr1,start1,start1+halfSize-1,arr2,end2-(halfSize-1),end2);
else
return getUpMedian(arr1,end1-(halfSize-1),end1,arr2,start2,start2+halfSize -1);
}
int getUpMedian(vector<int> arr1, vector<int> arr2) {//主函数
if(arr1.size() != arr2.size())
return -1;
if(arr1.size() == 0)
return -1;
return getUpMedian1(arr1,0,arr1.size()-1,arr2,0,arr1.size() -1 );
}
2.取不等长有序数组的最小K个数
题目:
给定两个有序数组arr1和arr2,在给定一个整数k,返回两个数组的所有数中第K小的数。要求:如果arr1的长度为N,arr2的长度为M。要求时间复杂度达到O(log(min{M,N}))
例如:arr1 = {1,2,3,4,5};arr2 = {3,4,5};K = 1; 因为1为所有数中最小的,所以返回1;
arr1 = {1,2,3};arr2 = {3,4,5,6};K = 4;因为3为所有数中第4小的数,所以返回3;
思路:
分三种情况考虑,假设arr1的长度N小于等于arr2的长度M
(1)若K<=N
结果为 arr1[0---K-1]和arr2[0---K-1]取中位数
(2)若 N<K<=M。先将arr2分为[0--K-N-1],[K-N-----K-1],[K,M-1]三部分
当arr2[K-N-1]>=arr1[N-1],结果为arr2[K-N-1]
否则,arr2[0--K-N-1]部分的所有数据一定至多在K-1位置(极端情况下,arr1[N]占据K位置)。而arr2[K,M-1]区间段的元素至少在K+1位置。因此结果对长度为N的两段区间段arr1[0,N-1]和arr2[K-N,K-1]取中位数即可。
(3)若K>M>N。先将划分arr1[0,K-M-1][K-M,N-1]两段区间,arr2[0,K-N-1][K-N,M-1]
当arr2[K-N-1]>=arr1[N-1],结果为arr2[K-N-1]
当arr1[K-M-1]>=arr2[M-1],结果为arr1[K-M-1]
两者不满足的话。则如前所叙述,arr1[0,K-M-1]和arr2[0,K-N-1]的元素都在位置K之前,至多为K-1。因此结果为长度为M+N-K的两段区间arr1[K-M,N-1]和arr2[K-N,M-1]的中位数。
时间复杂度最大为情况(2),即为所要求。
代码:
int findKthNum(vector<int> arr1, vector<int> arr2, int kth)
{
int size1 = arr1.size();
int size2 = arr2.size(); if(size1 > size2)
return findKthNum(arr2, arr1, kth);//ensur if(kth <= size1)
return getUpMedian(arr1, 0, kth - 1, arr2, 0, kth - 1);//前k个,取中位数即可
else if (kth <= size2 && kth > size1)
{
if(arr2[kth - size1 - 1] >= arr1[size1 - 1] )
return arr2[kth - size1 - 1];
else
return getUpMedian(arr1, 0, size1-1, arr2, kth-size1, kth-1);
}
else
{
if(arr2[kth-size1-1] >= arr1[size1-1])
return arr2[kth-size1-1];
if(arr1[kth-size2-1] >= arr2[size2-1])
return arr1[kth-size2-1];
return getUpMedian(arr1, kth-size2, size1-1, arr2, kth-size1, size2-1);
} }
参考:
1.[nowCoder] 两个长度相同有序数组的中位数
每天一道算法题目(18)——取等长有序数组的上中位数和不等长有序数组的第k小的数的更多相关文章
- 一道算法题目, 二行代码, Binary Tree
June 8, 2015 我最喜欢的一道算法题目, 二行代码. 编程序需要很强的逻辑思维, 多问几个为什么, 可不可以简化.想一想, 二行代码, 五分钟就可以搞定; 2015年网上大家热议的 Home ...
- 每天一道算法题(32)——输出数组中第k小的数
1.题目 快速输出第K小的数 2.思路 使用快速排序的思想,递归求解.若键值位置i与k相等,返回.若大于k,则在[start,i-1]中寻找第k大的数.若小于k.则在[i+1,end]中寻找第k+st ...
- 算法---数组总结篇2——找丢失的数,找最大最小,前k大,第k小的数
一.如何找出数组中丢失的数 题目描述:给定一个由n-1个整数组成的未排序的数组序列,其原始都是1到n中的不同的整数,请写出一个寻找数组序列中缺失整数的线性时间算法 方法1:累加求和 时间复杂度是O(N ...
- 算法总结之 在两个排序数组中找到第K小的数
给定两个有序数组arr1 和 arr2 ,再给定一个int K,返回所有的数中第K小的数 要求长度如果分别为 N M,时间复杂度O(log(min{M,N}),额外空间复杂度O(1) 解决此题的方法跟 ...
- 查找第K小的数 BFPRT算法
出处 http://blog.csdn.net/adong76/article/details/10071297 BFPRT算法是解决从n个数中选择第k大或第k小的数这个经典问题的著名算法,但很多人并 ...
- [nowCoder] 两个不等长数组求第K大数
给定两个有序数组arr1和arr2,在给定一个整数k,返回两个数组的所有数中第K小的数.例如:arr1 = {1,2,3,4,5};arr2 = {3,4,5};K = 1;因为1为所有数中最小的,所 ...
- 快速排序以及第k小元素的线性选择算法
简要介绍下快速排序的思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此 ...
- YTU 2420: C语言习题 不等长字符串排序
2420: C语言习题 不等长字符串排序 时间限制: 1 Sec 内存限制: 128 MB 提交: 460 解决: 239 题目描述 在主函数中输入n(n<=10)个不等长的字符串.用另一函 ...
- BFPRT算法(求第K小的数字)
BFPRT算法: 1.介绍: BFPRT算法又叫中位数的中位数算法,主要用于在无序数组中寻找第K大或第K小的数,它的最坏时间复杂度为O(n),它是由Blum,Floyd,Pratt,Rivest,Ta ...
随机推荐
- spring boot 基础篇 -- 集成接口测试Swagger
一.在pom.xml加入Swagger jar包引入 <dependency> <groupId>io.springfox</groupId> <artifa ...
- getBytes()详解
在java中,getBytes()方法如果不指定字符集,则得到的是一个操作系统默认的编码格式的字节数组:如果指定字符集,则得到的是在指定字符集下的字节数组,如: byte[] b_gbk = &quo ...
- Java_数据交换_JAXB_用法入门
一.前言 最近有个需求,需要进行xml 与 bean 的相互转化. 使用 JAXB 可完成这个需求. 二.概述 JAXB(Java Architecture for XML Binding) 是一个业 ...
- java学习笔记 --- 多线程(多线程的创建方式)
1.创建多线程方式1——继承Thread类. 步骤: A:自定义类MyThread继承Thread类. B:MyThread类里面重写run()? 为什么是run()方法呢? C:创建对象 D:启 ...
- AJAX的最小单元
$(function(){ $('#send').click(function(){ $.ajax({ type: "GET", url: "test.json" ...
- 一文搞定 Git 相关概念和常用指令
我几乎每天都使用 Git,但仍然无法记住很多命令. 通常,只需要记住下图中的 6 个命令就足以供日常使用.但是,为了确保使用地很顺滑,其实你应该记住 60 到 100 个命令. Git 相关术语 Gi ...
- centos 下配置oracle11gR2开机自启
这里使用的环境是 CentOS 6.6 ,并且已经装好了oracle11gR2 oracle启动分为两个步骤: 1.启动监听 2.启动服务 1.root 用户下修改ORATAB(将N该为Y): [ro ...
- BZOJ1280: Emmy卖猪pigs
BZOJ1280: Emmy卖猪pigs https://lydsy.com/JudgeOnline/problem.php?id=1280 分析: 这题感觉还好,因为是有时间顺序,所以拆点做最大流即 ...
- [ZOJ2587]Unique Attack
vjudge sol 最小割判定唯一性. 只要做完一个任意最小割后,判断一下是不是所有点都要么和\(S\)相连,要么和\(T\)相连. 只要两边各一次\(dfs\)就行了. code #include ...
- SpringMVC概要总结
架构流程 1. 用户发送请求至前端控制器DispatcherServlet 2. DispatcherServlet收到请求调用HandlerMapping处理器映射器. 3. 处理器映射器根据 ...