寻找两个已序数组中的第k大元素
1、问题描述
给定两个数组与
,其大小分别为
、
,假定它们都是已按照增序排序的数组,我们用尽可能快的方法去求两个数组合并后第
大的元素,其中,
。例如,对于数组
,
。我们记第
大的数为
,则
时,
。这是因为排序之后的数组
,第4大的数是4。我们针对这一个问题进行探讨。
2、算法一
第一眼看到这个题的时候,我们能够很快地想出来最基本的一种解法:对数组和
进行合并,然后求出其第
大的数,即找到答案。合并的过程,我们可以参考归并排序的合并子数组的过程,时间复杂度为
。下面给出算法:
int findKthMaxNumOfArrays(int *a,int m,int *b,int n,int k)
{
int *p=a;
int *q=b;
int i=0;
int j=0;
int cur=0;
while(i<m&&j<n)
{
if(a[i]<b[j])
{
cur++;
if(cur==k) return a[i];
i++;
}
else
{
cur++;
if(cur==k) return b[j];
j++;
}
}
while(i<m)
{
cur++;
if(cur==k) return a[i];
i++;
}
while(j<n)
{
cur++;
if(cur==k) return b[j];
j++;
}
}
3、算法二
实际上算法一的时间复杂度已经是线性的了。可是,是否存在更快的算法能够完成这项任务呢?答案是肯定的,时间复杂度可以缩短到时间内。在这种算法中,二分的思想十分重要。我们将数组
分为两半,前一部分的大小为
,后一部分为
;数组
同时分为这样两部分,第一部分的大小为
,第二部分的大小为
。如下图所示:


通过与
,我们将每个数组分为2部分,分别记为
、
和
、
。假定
,如果不是,我们只需要交换
、
两个数组即可。接下来,我们看第
大的数落在了哪个区间里面,令
,这个
实际上是包含了
,
,
。如果
时,则说明
肯定不在
里面,这是由于:
中的所有数
,而
中的所有数与
,而这部分数总共有
个,说明
是第
个,若
出现在
中,则说明
,与假设矛盾。我们可以得出该结论。因此,在判断之后,我们可以剔除数组
的
部分,然后再在新数组中寻找;另外,如果
,则说明
肯定不在
部分,这部分的证明同上一个证明相同,不再赘述。同样地,在判断之后,我们可以剔除数组
的
部分,然后再在新数组中寻找。基于这样一种思想,我们每次迭代,都删除了其中一个数组中一半的元素,时间复杂度大约可认为是
。
在实现的时候,我们需要特别注意边界条件,详细的代码如下:
int findKthMaxNumOfArrays(int *A, int m, int *B, int n, int k)
{
if(m == 0)return B[k-1];
if(n == 0)return A[k-1];
int i = m>>1, j = n>>1, *p, *q, t;
if(A[i] <= B[j])p = A, q = B;
else p = B, q = A, swap(i, j), swap(m, n);
t = i + j + 1;
if(t >= k)return func(p, m, q, j, k);
else if(t < k)return func(p+i+1, m-i-1, q, n, k-i-1);
}
4、扩展问题
通过算法二,我们很容易地解决一个类似的问题:求两个已序数组,
的中位数。所谓的中位数,对于一个有
个元素的已序数组,如果
是奇数,则中位数是第
个元素的值;如果
是偶数,则它的中位数是第
与第
数的平均值。对于
为奇数,则利用算法二求第
个元素的值即可,对于
为偶数,利用算法二求第
个与第
个元素的值,求其平均值即可。
对于这个问题,在LeetCode中有另外一种解法,但是阅读后发现其需要处理的个别case太多,相比而言没有本文所介绍的算法简洁。如果想要了解,给出链接:http://leetcode.com/2011/03/median-of-two-sorted-arrays.html。
作者:Chenny Chen
出处:http://www.cnblogs.com/XjChenny/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
寻找两个已序数组中的第k大元素的更多相关文章
- 【算法剖析】寻找两个已序数组中的第k大元素
1.问题描述 给定两个数组A与B,其大小分别为m.n,假定它们都是已按照增序排序的数组,我们用尽可能快的方法去求两个数组合并后第k大的元素,其中,1\le k\le(m+n).例如,对于数组A=[1, ...
- leetcode-4. 寻找两个正序数组的中位数
leetcode-4. 寻找两个正序数组的中位数. 给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2. 请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(l ...
- 17082 两个有序数序列中找第k小
17082 两个有序数序列中找第k小 时间限制:1000MS 内存限制:65535K 提交次数:0 通过次数:0 题型: 编程题 语言: 无限制 Description 已知两个已经排好序(非减 ...
- 17082 两个有序数序列中找第k小(优先做)
17082 两个有序数序列中找第k小(优先做) 时间限制:1000MS 内存限制:65535K提交次数:0 通过次数:0 题型: 编程题 语言: G++;GCC;VC Description 已 ...
- 17082 两个有序数序列中找第k小(优先做) O(logn)
17082 两个有序数序列中找第k小(优先做) 时间限制:1000MS 内存限制:65535K提交次数:0 通过次数:0 题型: 编程题 语言: G++;GCC;VC Description 已 ...
- 如何寻找无序数组中的第K大元素?
如何寻找无序数组中的第K大元素? 有这样一个算法题:有一个无序数组,要求找出数组中的第K大元素.比如给定的无序数组如下所示: 如果k=6,也就是要寻找第6大的元素,很显然,数组中第一大元素是24,第二 ...
- Leetcode 703. 数据流中的第K大元素
1.题目要求 设计一个找到数据流中第K大元素的类(class).注意是排序后的第K大元素,不是第K个不同的元素. 你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器, ...
- Java实现 LeetCode 703 数据流中的第K大元素(先序队列)
703. 数据流中的第K大元素 设计一个找到数据流中第K大元素的类(class).注意是排序后的第K大元素,不是第K个不同的元素. 你的 KthLargest 类需要一个同时接收整数 k 和整数数组n ...
- 微软面试题: LeetCode 4. 寻找两个正序数组的中位数 hard 出现次数:3
题目描述: 给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组的中位数. 进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决 ...
随机推荐
- 详解linux vi命令用法
vi是所有UNIX系统都会提供的屏幕编辑器,它提供了一个视窗设备,通过它可以编辑文件.当然,对UNIX系统略有所知的人,或多或少都觉得vi超级难用,但vi是最基本的编辑器,所以希望读者能好好把它学起来 ...
- effective C++ 札记 规定17 在单独的陈述newed对象插入智能指针
// Test.cpp : 自定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include &l ...
- EditPlus仿Sublime配色方案(三种任你选择)
[Options] Placement=2C00000002000000030000000083FFFF0083FFFFFFFFFFFFFFFFFFFFEA000000EE000000D6050000 ...
- SQL点滴10—使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比
原文:SQL点滴10-使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比 今天偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊.看了一位博主的文章 ...
- c++ 正則表達式
正則表達式是经常使用的一种方法.比較有名的类库是boost,可是这个类库在重了.全部就像找一些轻量级的类库. 后来发现准标准的库tr1已经非常方便了,微软vs2008 sp1 以上版本号都支持了.全部 ...
- 使用rem设计移动端自适应页面一(转载)
1.困扰多时的问题 在这之前做Web App开发的的时候,在自适应方面一般都是宽度通过百分比,高度以iPhone6跟iPhone5之间的一个平衡值写死,我们的设计稿都是iPhone5的640 * 11 ...
- Centos中如何配置Texlive2013中文字体的问题
Centos中如何配置Texlive2013中文字体的问题: 第一步是下载你需要的字体,我从windows/fonts中拷贝的比较多,你只要复制你需要的字体即可. 注意只要文件扩展名为ttf的文件,t ...
- 学习Sass之安装Sass
学习Sass之安装Sass 为什么使用Sass 作为前端(html.javascript.css)的三大马车之一的css,一直以静态语言存在,HTML5火遍大江南北了.javascript由于NODE ...
- (蓝牙)网络编程中,使用InputStream read方法读取数据阻塞的解决方法
问题如题,这个问题困扰了我好几天,今天终于解决了,感谢[1]. 首先,我要做的是android手机和电脑进行蓝牙通信,android发一句话,电脑端程序至少就要做到接受到那句话.android端发送信 ...
- SQLSERVER 总结1
数据:描述事物的符号记录 数据库:按照数据结构来组织和存储管理的数据仓库 数据库管理系统:位于用户与操作系统之间的一层数据管理软件 数据库系统:在计算机系统中引入数据库后的系统构成.由数据库,数据库管 ...