17082 两个有序数序列中找第k小(优先做)

时间限制:1000MS  内存限制:65535K
提交次数:0 通过次数:0

题型: 编程题   语言: G++;GCC;VC

Description

已知两个已经排好序(非减序)的序列X和Y,其中X的长度为m,Y长度为n,
现在请你用分治算法,找出X和Y的第k小的数,算法时间复杂度为O(max{logm, logn})。 此题请勿采用将序列X和Y合并找第k小的O(m+n)的一般方法,要充分利用X和Y已经排好序的这一特性。

输入格式

第一行有三个数,分别是长度m、长度n和k,中间空格相连(1<=m,n<=100000; 1<=k<=m+n)。
第二行m个数分别是非减序的序列X。第三行n个数分别是非减序的序列Y。

输出格式

序列X和Y的第k小的数。

输入样例

5 6 7
1 8 12 12 21
4 12 20 22 26 31

输出样例

20

提示

假设:X序列为X[xBeg...xEnd],而Y序列为Y[yBeg...yEnd]。

将序列X和Y都均分2段,即取X序列中间位置为 xMid (xMid = xBeg+(xEnd-xBeg)/2),也同理取序列Y中间位置为yMid。
比较X[xMid]和Y[yMid]的大小,此时记录X左段和Y左段元素个数合计为halfLen,即halfLen = xMid-xBeg+yMid-yBeg+2。 1. 当X[xMid] < Y[yMid]时,在合并的数组中,原X[xBeg...xMid]所有元素一定在Y[yMid]的左侧,
(1) 若k < halfLen,则此时第k大的元素一定不会大于Y[yMid]这个元素,
故以后没有必要搜索 Y[yMid...yEnd]这些元素,可弃Y后半段数据。
此时只需递归的对X序列+Y序列的前半段,去搜索第k小的数。 (2) 若k >= halfLen,则此时第k大的元素一定不会小于X[xMid]这个元素,
故以后没有必要搜索 X[xBeg...xMid]这些元素,可弃X前半段数据。
此时只需递归的对X序列的后半段+Y序列,去搜索第 k-(xMid-xBeg+1)小的数。 2. 当X[xMid] >= Y[yMid]时,在合并的数组中,原Y[yBeg...yMid]的所有元素一定在X[xMid]的左侧,
(1) 若k < halfLen,则此时第k大的元素一定不会大于X[xMid]这个元素,
故以后没有必要搜索 X[xMid...xEnd]这些元素,可弃X后半段数据。
此时只需递归的对X序列的前半段+Y序列,去搜索第k小的数。 (2) 若k >= halfLen,则此时第k大的元素一定不会小于Y[yMid]这个元素,
故以后没有必要搜索 Y[yBeg...yMid]这些元素,可弃Y前半段数据。
此时只需递归的对X序列+Y序列的后半段,去搜索第 k-(yMid-yBeg+1)小的数。 递归的边界,如何来写?
1) if (xBeg > xEnd) return Y[yBeg + k - 1]; //X序列为空时,直接返回Y序列的第k小元素。
2) if (yBeg > yEnd) return X[xBeg + k - 1]; //Y序列为空时,直接返回X序列的第k小元素。 效率分析: T(m,n)表示对长度为m的有序的X序列和长度为n的有序的Y序列,搜索第k小元素的复杂度。
T(m,n)=1 m=0或n=0
T(m,n) <= max{T(m/2,n), T(m,n/2)} + O(1) 则T(m,n) = O(max{logm, logn})

作者

zhengchan

首先,如果a数组取a[k/2]那个值,b数组需要取b[k - k/2]那个值,这样使得两者加起来是k个,然后,如果a[k/2] > b[k - k/2],那么b[k-k/2]肯定不会是答案,又因为递增,所以b[k-k/2]前面的可以不用考虑了,直接把这部分pass掉。同理其他。

注意的是,每次都需要在比较短的那个数组里面取值,再去长度大的那个数组里面找k - k/2

#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = 1e5 + ;
int a[maxn], b[maxn]; int findkthMin(int aBe, int aEn, int bBe, int bEn, int k) {
if (aEn < aBe) return b[bBe + k - ];
if (bEn < bBe) return a[aBe + k - ];
if (k == ) return min(a[aBe], b[bBe]);
if (aEn - aBe < bEn - bBe) {
int asel = min(k / , aEn - aBe + ), bsel = k - asel;
int posa = aBe + asel - , posb = bBe + bsel - ;
if (a[posa] == b[posb]) return a[posa];
if (a[posa] < b[posb]) return findkthMin(posa + , aEn, bBe, bEn, k - asel);
if (a[posa] > b[posb]) return findkthMin(aBe, aEn, posb + , bEn, k - bsel);
} else {
int bsel = min(k / , bEn - bBe + ), asel = k - bsel;
int posa = aBe + asel - , posb = bBe + bsel - ;
if (a[posa] == b[posb]) return a[posa];
if (a[posa] < b[posb]) return findkthMin(posa + , aEn, bBe, bEn, k - asel);
if (a[posa] > b[posb]) return findkthMin(aBe, aEn, posb + , bEn, k - bsel);
}
} void work() {
int n, m, k;
cin >> n >> m >> k;
for (int i = ; i <= n; ++i) cin >> a[i];
for (int j = ; j <= m; ++j) cin >> b[j];
// printf("%d\n", find_kth(a, n, b, m, k));
printf("%d\n", findkthMin(, n, , m, k));
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return ;
}

17082 两个有序数序列中找第k小(优先做) O(logn)的更多相关文章

  1. 17082 两个有序数序列中找第k小

    17082 两个有序数序列中找第k小 时间限制:1000MS  内存限制:65535K 提交次数:0 通过次数:0 题型: 编程题   语言: 无限制 Description 已知两个已经排好序(非减 ...

  2. 17082 两个有序数序列中找第k小(优先做)

    17082 两个有序数序列中找第k小(优先做) 时间限制:1000MS  内存限制:65535K提交次数:0 通过次数:0 题型: 编程题   语言: G++;GCC;VC Description 已 ...

  3. 寻找两个已序数组中的第k大元素

    寻找两个已序数组中的第k大元素 1.问题描述 给定两个数组与,其大小分别为.,假定它们都是已按照增序排序的数组,我们用尽可能快的方法去求两个数组合并后第大的元素,其中,.例如,对于数组,.我们记第大的 ...

  4. 【算法剖析】寻找两个已序数组中的第k大元素

    1.问题描述 给定两个数组A与B,其大小分别为m.n,假定它们都是已按照增序排序的数组,我们用尽可能快的方法去求两个数组合并后第k大的元素,其中,1\le k\le(m+n).例如,对于数组A=[1, ...

  5. 在线性级别时间内找出无序序列中的第k个元素

    在一个无序序列中找出第k个元素,对于k很小或者很大时可以采取特殊的方法,比如用堆排序来实现 .但是对于与序列长度N成正比的k来说,就不是一件容易的事了,可能最容易想到的就是先将无序序列排序再遍历即可找 ...

  6. 两个有序数列找第k小

    给定一个数组,数组中的数据无序,在一个数组中找出其第k个最小的数,例如对于数组x,x = {3,2,1,4,5,6},则其第2个最小的数为2  两个有序数组 找第k小 * 方案一 合并遍历 * 二:游 ...

  7. [LeetCode] Find K-th Smallest Pair Distance 找第K小的数对儿距离

    Given an integer array, return the k-th smallest distance among all the pairs. The distance of a pai ...

  8. 快速排序算法的实现 && 随机生成区间里的数 && O(n)找第k小 && O(nlogk)找前k大

    思路:固定一个数,把这个数放到合法的位置,然后左边的数都是比它小,右边的数都是比它大 固定权值选的是第一个数,或者一个随机数 因为固定的是左端点,所以一开始需要在右端点开始,找一个小于权值的数,从左端 ...

  9. [LeetCode] 719. Find K-th Smallest Pair Distance 找第K小的数对儿距离

    Given an integer array, return the k-th smallest distance among all the pairs. The distance of a pai ...

随机推荐

  1. 牛客网java基础题分类

    http://www.cnblogs.com/tptptptp/p/5904075.html

  2. Tomact和XML配置文件

    1 Http协议2 Tomcat服务器3 编写xml4 通过DTD约束编写指定格式的XML 5 通过Schema约束编写指定格式的XML6 使用D0M4J解析xml================== ...

  3. mysql双机热备份的实现步骤

    MySQL 提供了数据库的同步功能,这对我们实现数据库的冗灾.备份.恢复.负载均衡等都是有极大帮助的.本文描述了常见的同步设置方法.<?xml:namespace prefix = o /> ...

  4. 【C#】 创建、部署和调用WebService的简单示例

    C# 创建.部署和调用WebService的简单示例 <div class="postBody"> <div id="cnblogs_post_body ...

  5. UITouch

    触摸事件基本都是发生在 viewController 中,首先触摸的对象是视图,而视图的类 UIView 继承了 UIRespnder 类,但是要对事件作出处理,还需要重写 UIResponder 类 ...

  6. asp遍历前端的所有控件

    //遍历ID为Panel1的panel里的所有label控件 foreach (Control ctl in this.Panel1.Controls) { //判断类型为Label的 if (ctl ...

  7. Dynamic Rankings(整体二分)

    Dynamic Rankings(整体二分) 带修区间第k小.\(n,q\le 10^4\). 这次我们旧瓶装新酒,不用带修主席树.我们用整体二分!整体二分是啥东西呢? 二分答案可以解决一次询问的问题 ...

  8. P2488 [SDOI2011]工作安排 费用流

    \(\color{#0066ff}{ 题目描述 }\) 你的任务是制定出一个产品的分配方案,使得订单条件被满足,并且所有员工的愤怒值之和最小.由于我们并不想使用Special Judge,也为了使选手 ...

  9. 公有云Docker镜像P2P加速之路:安全篇

    一.问题 在使用Docker运行容器化应用时,宿主机通常先要从Registry服务(如Docker Hub)下载相应的镜像(image).这种镜像机制在开发环境中使用还是很有效的,团队成员之间可以很方 ...

  10. CSS(十二).transition的应用之CSS中心扩散

    实现 css中心向两边扩散的两个核心 1.hover 之前的 垂直居中 2.文字置于最顶层 顺道来讲讲hover 伪元素是不支持 hover 的,不过我们可以给普通的 tag 标签添加 hover 以 ...