转载博客:http://www.cnblogs.com/buptLizer/archive/2012/03/31/2427579.html

题目意思:给出两个排好序的数组 ,不妨设为a,b都按升序排列,及k的值,求出第k大的那个元素。

分析这个题目,如果题目没有时间复杂度的要求,我们可以定义两个指针i,j分别指向a,b,如果a[i]<b[j]则i++否则

j++,这个记录下走了多少步,如果==k步,则找到了第k大的元素,复杂度为O(k).

那么如果有复杂度的要求,要求为O(log(len_a+len_b))呢,这个就得好好考虑,怎么利用二分来解决这个问题。

解法一:

假如第k大的数在a中,设置a[mid],那么肯定有b[k-mid-1]<=a[mid]<=b[k-mid],这是由于a中已经有mid个元素<a[mid]了,

则b中肯定还有k-mid - 1个元素小于a[mid],所以我们判断

若b[k-mid-2]<=a[mid]<=b[k-mid-1], 返回a[mid]

若a[mid] < b[k-mid-2] 说明a[mid]小于第k个元素值,a.low = a.mid + 1

若a[mid] > b[k-mid-1],说明a[mid]大于第k个元素值,a.high = a.mid - 1

结束条件为a.low > a.high 如果未找到,则假设存在于b中,再判断一次

代码如下:

int get_k_from_sorted_array(int* a, int* b, int low, int high, int k, int len)
{
if(low > high)
return -1;
int mid = low + (high - low)/2;
//a中元素个数小于k个,那么k - 2 - mid就可能超出b的下标范围
if(k - 2 - mid >= len)
return get_k_from_sorted_array(a, b, mid + 1, high, k, len);
if(k - 1 - mid < len)
{
//判断b数据中是否存在b[k-1-mid]
if(a[mid] >= b[k - mid - 2] && a[mid] <= b[k - mid - 1])
return a[mid];
}
else
{
if(a[mid] >= b[k - mid - 2])
return a[mid];
}
if(a[mid] < b[k - mid - 2])
return get_k_from_sorted_array(a, b, mid + 1, high, k, len);
return get_k_from_sorted_array(a, b, low, mid - 1, k, len);
}
int _func(int* a, int a_len, int* b, int b_len, int k)
{
int rst = 0;
if(a_len + b_len + 2 < k)
return -1;
int p1 = a_len > k - 1 ? k - 1: a_len;
int p2 = b_len > k - 1 ? k - 1: b_len;
rst = get_k_from_sorted_array(a, b, 0, p1, k, 4);
if(-1 == rst)
{
rst = get_k_from_sorted_array(b, a, 0, p2, k, 5);
}
return rst;
}

解法二:

判断a[mid_a] 与 b[mid_b]的关系
 如果a[mida] < b[mid_b]

1)k小于等于mida + midb + 1,那么b数组从mid_b开始就没有用了,缩小b的搜索范围
 2)k大于mida + midb + 1, 那么a数组从low到mid_a开始就没用了,缩小a的搜索范围
 3)终止条件是 a搜索完 返回b中元素或者相反

代码如下:

int get_k_from_sorted_array2(int* a, int*b, int la, int ha, int lb, int hb, int k)
{
if(la > ha)
return b[lb + k - 1];
if(lb > hb)
return a[la + k - 1];
int mida = (la + ha)>>1;
int midb = (lb + hb)>>1;
int num = mida- la + midb - lb + 1;
cout<<la<<" "<<ha<<" "<<lb<<" "<<hb<<" "<<num<<" "<<a[mida]<<" "<<b[midb]<<endl; if(a[mida] <= b[midb])
{
if(k <= num)
return get_k_from_sorted_array2(a, b, la, ha, lb, midb - 1, k);
else
return get_k_from_sorted_array2(a, b, mida + 1, ha, lb, hb, k - (mida - la + 1));
}
else
{
if(k <= num)
return get_k_from_sorted_array2(a, b, la, mida - 1, lb, hb, k);
else
return get_k_from_sorted_array2(a, b, la, ha, midb + 1, hb, k - (midb - lb + 1));
}
}
int _func2(int* a, int a_len, int* b, int b_len, int k)
{
int rst = 0;
if(a_len + b_len < k)
return -1;
int p1 = a_len > k ? k : a_len;
int p2 = b_len > k ? k : b_len;
cout<<p1<<" "<<p2<<endl;
rst = get_k_from_sorted_array2(a, b, 0, p1 - 1, 0, p2 - 1, k);
return rst;
}

认真对待每一道算法题 之 两个排序好的数组寻找的第k个大的数的更多相关文章

  1. 每天一道算法题(4)——O(1)时间内删除链表节点

    1.思路 假设链表......---A--B--C--D....,要删除B.一般的做法是遍历链表并记录前驱节点,修改指针,时间为O(n).删除节点的实质为更改后驱指针指向.这里,复制C的内容至B(此时 ...

  2. java:合并两个排序的整数数组A和B变成一个新的数组。新数组也要有序。

    合并两个排序的整数数组A和B变成一个新的数组.新数组也要有序. 样例 1: 输入: A=[1], B=[1] 输出:[1,1] 样例解释: 返回合并后的数组. 样例 2: 输入: A=[1,2,3,4 ...

  3. 9.11排序与查找(一)——给定两个排序后的数组A和B,当中A的末端有足够的缓冲空间容纳B。将B合并入A并排序

    /**  * 功能:给定两个排序后的数组A和B,当中A的末端有足够的缓冲空间容纳B.将B合并入A并排序. */ /** * 问题:假设将元素插入数组A的前端,就必须将原有的元素向后移动,以腾出空间. ...

  4. 从一道算法题实现一个文本diff小工具

    众所周知,很多社区都是有内容审核机制的,除了第一次发布,后续的修改也需要审核,最粗暴的方式当然是从头再看一遍,但是编辑肯定想弄死你,显然这样效率比较低,比如就改了一个错别字,再看几遍可能也看不出来,所 ...

  5. 【每天一道算法题】时间复杂度为O(n)的排序

    有1,2,……一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度为O(1),使用交换,而且一次只能交换两个数. 这个是以前看到的算法题,题目不难.但是要求比较多,排序算法中,时间 ...

  6. 提前批笔试一道算法题的Java实现

    题目描述 这是2021广联达校招提前批笔试算法题之一. 我们希望一个序列中的元素是各不相同的,但是理想和显示往往是有差距的.现在给出一个序列A,其中难免有相同的元素,现在提供了一种变化方式,使得经过若 ...

  7. 每天一道算法题(14)——N个降序数组,找到最大的K个数

     题目: 假定有20个有序数组,每个数组有500个数字,降序排列,数字类型32位uint数值,现在需要取出这10000个数字中最大的500个. 思路 (1).建立大顶堆,维度为数组的个数,这里为20( ...

  8. 每天一道算法题-leetcode136-只出现一次的数字

    前言 打卡第一天 2019.10.26日打卡 算法,即解决问题的方法.同一个问题,使用不同的算法,虽然得到的结果相同,但是耗费的时间和资源是不同的.这就需要我们学习算法,找出哪个算法更好. 大家都知道 ...

  9. 一道算法题加深我对C++中map函数的理解

    一.一道题目引发我对map函数的考量 首先是题目大意:有n个银行,a[i]表示这个人在第i个银行有a[i]块钱(可以是负数),所有银行的钱加起来正好是0.每次只能在相邻的银行之间转账,问最少要转多少次 ...

随机推荐

  1. 能源项目xml文件 -- springMVC-servlet.xml

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  2. selenium+python笔记7

    #!/usr/bin/env python # -*- coding: utf-8 -*- """ @desc: 测试126邮箱的登陆功能 1.使用公共方法public. ...

  3. cf(#div1 B. Dreamoon and Sets)(数论)

    B. Dreamoon and Sets time limit per test 1 second memory limit per test 256 megabytes input standard ...

  4. hdu----(2848)Repository(trie树变形)

    Repository Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  5. 10大html5前端框架

    Bootstrap 首先说 Bootstrap,估计你也猜到会先说或者一定会有这个( 呵呵了 ),这是说明它的强大之处,拥有框架一壁江山的势气.自己刚入道的时候本着代码任何一个字母都得自己敲出来挡我者 ...

  6. Java 线程综述

    线程重在 线程同步和线程通信的编程 1.线程与进程?  线程是指程序在执行过程中,能够执行程序代码的一个执行单元.线程的状态:运行.就绪.挂起(suspend).结束; 进程是指一段正在执行的程序. ...

  7. uva 1629

    1629 - Cake slicing Time limit: 3.000 seconds A rectangular cake with a grid of m * n <tex2html_v ...

  8. 百度Tera数据库介绍——类似cassandra,levelDB

    转自:https://my.oschina.net/u/2982571/blog/775452 设计背景 百度的链接处理系统每天处理万亿级的超链数据,在过去,这是一系列Mapreduce的批量过程,对 ...

  9. C++调用父类的构造函数规则

    构造方法用来初始化类的对象,与父类的其它成员不同,它不能被子类继承(子类可以继承父类所有的成员变量和成员方法,但不继承父类的构造方法).因此,在创建子类对象时,为了初始化从父类继承来的数据成员,系统需 ...

  10. Storm(4) - Distributed Remote Procedure Calls

    Using DRPC to complete the required processing 1. Create a new branch of your source using the follo ...