两个有序数组中查找第K大数

题目:两个数组A、B,长度分别为m、n,即A(m)、B(n),分别是递增数组。求第K大的数字。

方法一:

简单的办法,使用Merge Sort,首先将两个数组合并,然后在枚举查找。这个算法的时间复杂度是O(m+n)、空间复杂度也是O(M+n)。

这个方法其实没有考虑到有第K大数为两个相同数字的情况。

方法二:

这里需要两个前提条件,

1、如果K是中位数,则(M+n)是奇数还是偶数是有关系的。如果是奇数,那么中位数唯一,如果是偶数就有两个中位数,可以随便取一个。

2、如果找到的第K大数是x,假如在A的位置是A(x),在B中的位置是B(x),则Ax+Bx-1=k是成立的。

接下来是具体实现逻辑:

1、首先假设K大数在A数组中,首先检查 (m/(m+n))*(k-1),假设其值为A1。然后检查B中(k+1-(n/(m+n))*(k-1))假设为B1,检查A1、B1是否相等,或者大于B中的第(k+1-(n/(m+n))*(k-1)),并且小于(k+1-(n/(m+n))*(k-1))+1个元素。满足条件就可以知道A1就是所求,否则看条件2。

2、如果两个条件都不满足,那么需要判断第K个元素是位于A1左边还是右边。

如果A1>B1,那么K肯定不在A[0, (m/(m + n)) * (k - 1)]以及B[(k + 1 - (m/(m + n)) * (k - 1))+ 1, n]中;

如果A1<B1,那么K肯定不在A[ (m/(m + n)) * (k - 1), m]以及B[0, (k + 1 - (m/(m + n)) * (k - 1))]中。

第K个元素有可能在B中,同理可以假设在B中,再进行一次搜索。复杂度为log(m)+log(n)。

具体代码如下:

int kthsmallest(int *a,int m,int *b,int n,int k) {

if (m == 0) {

return b[k - 1];

}

if (n == 0) {

return a[k - 1];

}

if (k == 1) {

return (a[0] < b[0])?a[0]:b[0];

}

if (k == m + n) {

return (a[m - 1] > b[n - 1])?a[m - 1]:b[n - 1];

}

int i = ((double) m) / (m + n) * (k - 1);

int j = k - 1 - i;

if (j >= n) {

j = n - 1;

i = k - n;

}

if (((i == 0) || (a[i - 1] <= b[j])) && (b[j] <= a[i])) {

return b[j];

}

if (((j == 0) || (b[j - 1] <= a[i])) && (a[i] <= b[j])) {

return a[i];

}

if (a[i] <= b[j]) {

return kthsmallest(a + i + 1, m - i - 1, b, j, k - i - 1);

} else {

return kthsmallest(a, i, b + j + 1, n - j - 1, k - j - 1);

}

}

方法三:

当然也可以在方法一的基础上,采用一些二分的办法进行优化,但是这种算法

参考资料:

1、http://www.cnblogs.com/davidluo/articles/k-smallest-element-of-two-sorted-array.html

2、http://blog.csdn.net/realxie/article/details/8078043

3、http://blog.csdn.net/shifuwawa/article/details/6121573

4、http://eriol.iteye.com/blog/1172098

时间: 2024-07-30 23:52:00

两个有序数组中查找第K大数的相关文章

Coursera Algorithms week3 快速排序 练习测验: Selection in two sorted arrays(从两个有序数组中寻找第K大元素)

题目原文 Selection in two sorted arrays. Given two sorted arrays a[] and b[], of sizes n1 and n2, respectively, design an algorithm to find the kth largest key. The order  of growth of the worst case running time of your algorithm should be logn, where n

快速查找无序数组中的第K大数?

1.题目分析: 查找无序数组中的第K大数,直观感觉便是先排好序再找到下标为K-1的元素,时间复杂度O(NlgN).在此,我们想探索是否存在时间复杂度 < O(NlgN),而且近似等于O(N)的高效算法. 还记得我们快速排序的思想麽?通过“partition”递归划分前后部分.在本问题求解策略中,基于快排的划分函数可以利用“夹击法”,不断从原来的区间[0,n-1]向中间搜索第k大的数,大概搜索方向见下图: 2.参考代码: 1 #include <cstdio> 2 3 #define sw

C语言编程 在整型有序数组中查找想要的数字并且返回下标

遇到"有序"数组中查找元素类的题,优先考虑折半查找(二分查找) 做法核心是利用所定义的下标left和right与mid(由计算得来)下标的比较来逐渐缩短查找范围,达到一个阈值后即为找到. 源代码如下: #include<stdio.h> #include<stdlib.h> int search(int a[], int x, int left, int right)//定义二分查找函数 { while (left <= right) { int mid

两个有序数组,找第k小的数//未完

1.题目描述:a,b两个有序数组,找出第k小的数,logk,二分查找,1个小于怎么办? 2.思路: 对于数组A . B , 如果 B[pb] < A[pa] && B[pb] > A[pa - 1], 那么 B[pb] 一定是第 pa + pb + 1  小的数.比如数组A = {1, 8, 10, 20}, B = {5, 9, 22, 110},pa = 2, pb = 1, 这时,(B[pb] = 9) < (A[pa] =10) && (B[pb]

(算法)旋转有序数组中查找某个数

题目: 假设有个有序数组在某个位置旋转,得到新的数组,即为旋转有序数组.如:(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). 现给定一个这样的数组,在数组中查找某个数.如果找到,返回下标,否则返回-1: 思路: 思路1: 考虑一个旋转有序数组的特点:前面部分是递增的,后面部分也是递增的,即先后两部分都为递增有序数组,因此可以用二分查找来做. 假设数组为A,下标从left到right,查找的数字为target,那么mid=(left+((right

9.27 在两个排序数组中找到第K小的数

[题目]: 给定两个有序数组arr1和arr2,再给定一个整数k,返回所有的数中第K小的数 举例: arr1=[1, 2, 3, 4, 5],arr2=[3, 4, 5],k=1 1是所有数中第1小的数,所以返回1 arr1=[1, 2, 3],arr2=[3, 4, 5, 6],k=4 3是所有数中第4小的数,所以返回3 [要求]: 如果arr1的长度为N,arr2的长度为M,时间复杂度清达到O(log(min{M, N})),额外空间复杂度为O(1) 题目来源:左程云老师<程序员代码面试指南

写代码可以在整型有序数组中查找想要的数字

思路:对数组中的数字进行查找并与目标数字进行比较,一样则可以找到,不一样则没有. 方法一:在有序的数组中查找一个数字,可以用一个循环的方式将每一个数字依次查找然后挑出所求数字. 1 #include<stdio.h> 2 #define _CRT_SECURE_NO_WARNINGS 3 4 int Find_num(int a[], int size, int num) 5 { 6 for (int i = 0;i < size; i++) 7 { 8 if (a[i] == num)

两个有序数组中的交集

题目: 两个含有n个元素的有序(非降序)整形数组a和b(数组a和b中都没有重复元素),求出其共同元素 a = [0,1,2,3,4] b = [1,3,5,7,9] 那么交集为{1,3} 解法1:很简单,依次遍历 vector<int> commonValue1(vector<int>a, vector<int> b){ vector<int> result; if (a.size() < 1 || b.size() < 1) return re

多个有序数列中查找第k小值

问题描述:现有n个有序序列如(2,3,9),(3,5,11,23),(1,4,7,9,15,17,20),(8,15,35,9),(20,30,40),请求出第k小值. 问题分析:可用多路归并排序将所有序列进行排序后取第k个值,但是只要求求出第k小值将所有数组排序未免显得有点浪费,所以我们可以使用包含k个元素的堆完成,对于每组元素取出前k小的,依次进行比较,得到总的前k小 执行步骤: 一.建初堆:从第一组数中取出前k小的元素建初始大根堆(若不足k个则取全部元素), 二. 1 .补充堆:若堆中元素