认真对待每一道算法题 之 两个排序好的数组寻找的第k个大的数
转载博客: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个大的数的更多相关文章
- 每天一道算法题(4)——O(1)时间内删除链表节点
1.思路 假设链表......---A--B--C--D....,要删除B.一般的做法是遍历链表并记录前驱节点,修改指针,时间为O(n).删除节点的实质为更改后驱指针指向.这里,复制C的内容至B(此时 ...
- java:合并两个排序的整数数组A和B变成一个新的数组。新数组也要有序。
合并两个排序的整数数组A和B变成一个新的数组.新数组也要有序. 样例 1: 输入: A=[1], B=[1] 输出:[1,1] 样例解释: 返回合并后的数组. 样例 2: 输入: A=[1,2,3,4 ...
- 9.11排序与查找(一)——给定两个排序后的数组A和B,当中A的末端有足够的缓冲空间容纳B。将B合并入A并排序
/** * 功能:给定两个排序后的数组A和B,当中A的末端有足够的缓冲空间容纳B.将B合并入A并排序. */ /** * 问题:假设将元素插入数组A的前端,就必须将原有的元素向后移动,以腾出空间. ...
- 从一道算法题实现一个文本diff小工具
众所周知,很多社区都是有内容审核机制的,除了第一次发布,后续的修改也需要审核,最粗暴的方式当然是从头再看一遍,但是编辑肯定想弄死你,显然这样效率比较低,比如就改了一个错别字,再看几遍可能也看不出来,所 ...
- 【每天一道算法题】时间复杂度为O(n)的排序
有1,2,……一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度为O(1),使用交换,而且一次只能交换两个数. 这个是以前看到的算法题,题目不难.但是要求比较多,排序算法中,时间 ...
- 提前批笔试一道算法题的Java实现
题目描述 这是2021广联达校招提前批笔试算法题之一. 我们希望一个序列中的元素是各不相同的,但是理想和显示往往是有差距的.现在给出一个序列A,其中难免有相同的元素,现在提供了一种变化方式,使得经过若 ...
- 每天一道算法题(14)——N个降序数组,找到最大的K个数
题目: 假定有20个有序数组,每个数组有500个数字,降序排列,数字类型32位uint数值,现在需要取出这10000个数字中最大的500个. 思路 (1).建立大顶堆,维度为数组的个数,这里为20( ...
- 每天一道算法题-leetcode136-只出现一次的数字
前言 打卡第一天 2019.10.26日打卡 算法,即解决问题的方法.同一个问题,使用不同的算法,虽然得到的结果相同,但是耗费的时间和资源是不同的.这就需要我们学习算法,找出哪个算法更好. 大家都知道 ...
- 一道算法题加深我对C++中map函数的理解
一.一道题目引发我对map函数的考量 首先是题目大意:有n个银行,a[i]表示这个人在第i个银行有a[i]块钱(可以是负数),所有银行的钱加起来正好是0.每次只能在相邻的银行之间转账,问最少要转多少次 ...
随机推荐
- 一个最简html5文档来说明html5的新特性和写法
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="utf-8&quo ...
- 滚动条--nicescroll插件(兼容各种浏览器,低至IE5)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- OC 实例变量(Instance Var)和成员变量(member var)区别
摘要: Objective-C 引入了“实例变量"的概念,但同时, 也经常出现 “成员变量”的声音. 到底什么是实例变量,什么是成员变量,二者的区别是什么呢? 今天查看apple 的官方 ...
- android:configChanges属性
对android:configChanges属性,一般认为有以下几点: 1.不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏 ...
- jquery iframe高度自适应
$(document).ready(function () { $("#test").load(function () { var thisheight = $(this).con ...
- ajax的data传参的两种方式
ajax的data传参的两种方式 本文为转载. 1.[javascript] view plain copy /** * 订单取消 * @return {Boolean} 处理是否成功 */ func ...
- Objective-C(一简介)
Objective-C简介 通常写作ObjC和较少用的Objective C或Obj-C,是扩充C的面向对象编程语言.它主要使用于Mac OS X和GNUstep这两个使用OpenStep标准的系统, ...
- linux 一些命令
1.查看cpu个数 cat /proc/cpuinfo |grep "physical id" |sort | uniq |wc -l 2 2.查看cpu逻辑个数 cat /pro ...
- FZU 2027 单词问题 map标记字符串典型问题
题目链接:单词问题 找一个字符串里的所有单词,重复的只输出一次.关于map函数key值是字符串的问题一直比较含糊... 挣扎了一番,大概是,map的key值是char型数组的时候,标记的是地址,于是有 ...
- easyui datagrid高度自适应问题
最近在使用datagrid的时候,发现在panel中嵌入一个datagrid时,当panel缩小时,datagrid下面会有一块空白,datagrid高度不能自适应,解决方法是在datagrid外面加 ...