转载博客: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. (08)odoo继承机制

    * 全局的引用    所有的的模型定义外,都在注册中心注册了,我们可以用全局变量来引用这些模型    self.env[mode name] 比如得到合作伙伴这个模型 self.evn['res.pa ...

  2. content.boundingRectWithSize计算出来的高度不准

      计算出来的高度会少一行的高度,最后一行会显示不全.减掉padding会解决这个问题.   let padding = self.reviewText.textContainer.lineFragm ...

  3. MD4C/CO46/MD04一个很棒的工单缺料分析

    大家好~~~ 之前在MD04物料分析的时候,看到有订单预留,双击有个订单报告可以显示一个订单物料是否缺料清单 这个单独的工单分析可以在T-code:MD4C,CO46查看,如果只是单独的使用,那么这两 ...

  4. Android中 在显示ImageView时图片上面和下面都出现一段空白区间的解决办法

    开始的时候是在ScrollView中显示ImageView的时候出现这样的问题,以为是要对ScrollView进行设置的,后来发现单独显示一个ImageView的时候也会出现这样的问题,由此才知道是应 ...

  5. Objective-C(面向对象的三大特性)

    封装 set方法 作用:提供一个方法给外界设置成员变量值,可以在方法里面进行过滤 命名规范 1. 方法名必须以set开头 2. set后面跟上成员变量的名称,成员变量的首字母必须大写 3. 返回值一定 ...

  6. [转]Java并发的四种风味:Thread、Executor、ForkJoin和Actor

    这篇文章讨论了Java应用中并行处理的多种方法.从自己管理Java线程,到各种更好几的解决方法,Executor服务.ForkJoin 框架以及计算中的Actor模型. Java并发编程的4种风格:T ...

  7. LaTeX测试

    首先输出个\(\LaTeX\ \),看上去非常高端! 然后上论文,测试以后发现不行QAQQQ 貌似只能插入一个公式来着...比如:$\theta(\vec{u},\ \vec{v}) = arccos ...

  8. ANGULAR 开发用户选择器指令

    在开发表单时,我们需要使用经常需要使用到用户选择器,用户的数据一般使用如下方式存储: 用户1,用户2,用户3   我们可以使用angular指令实现选择器. <!DOCTYPE html> ...

  9. js 日期时间控制器

    /////////////////////////调用实例 // <div> // <span>交易查询:</span> <span>从 // < ...

  10. 目前几款基于html5的前端框架:如Bootstrap、Foundation、Semantic UI 、Amaze UI

    Bootstrap是由Twitter在2011年8月推出的开源WEB前端框架,集合CSS 和HTML,使用了最新的浏览器技术,为快速WEB开发提供了一套前端工具包,包括布局.网格.表格.按钮.表单.导 ...