求两个已排序的数组中所有元素的第K大(小)
2015-06-15 11:24
337 查看
1.reference
Creative Commonshttps://github.com/soulmachine/leetcode
2.解题思路
以下均假设A[0…m-1],B[0…n-1];1)O(n)
假设A,B均以降序排列,声明两个指针p,q。p指向A[0], q指向B[0]。再来一个count=0,用来表示当前已经到第count大了。然后指针开始游,如果*p > *q,则p++, count++;如果*p < *q,则q++, count++;而如果相等,两个游标选一个走即可,同时count++。最后当count==k时,就找到了所有元素的第K大了。
2)O(log(n))
上面O(n)的做法是一个一个剪,而这里,就是一半一半地剪。为了方便理解,这里就是求两个数组的第K小元素(原理是一样的,第K小即为第(m+n-k)大嘛),且A,B均以升序排列。因为A, B数组均已排好序,所以有如下结论(假设K为偶数,奇数同理)。
1’ A[] 或 B[] 中有个为空,则直接B[k-1]或A[k-1];
2’ 假设m,n>=k/2 (如果不满足,则下标取自己的上限即可)
1.A[k/2-1] < B[k/2-1]:删除A[0…k/2-1],第k小肯定不在里面。因为AUB之后,A[0…k/2-1]内的所有元素均在B[k/2-1]此元素之前,而两组数据个数总和才为k个。
2.A[k/2-1] > B[k/2-1]:删除B[0…k/2-1],第k小肯定不在里面。理由同上。
3.A[k/2-1] = B[k/2-1]:找到了第k小,即为A[k/2-1]=B[k/2-1]。
因此,由上述条件我们可以推出利用递归函数解决问题是极为方便的。递归过程及结束条件如下所示(设m < n,暂不防御型编程)
1.如果m=0,则return B[k-1];
2.如果k=1,则return min(A[0], B[0]);
3.m可能是小于k/2的,所以依上面分析取自己上限m即可,即有
若A[min(m, k/2)-1] < B[k-min(m, k/2)-1]:删除A[…],代入递归函数继续。
若A[min(m, k/2)-1] > B[k-min(m, k/2)-1]:删除B[…],代入递归函数继续。
若A[min(m, k/2)-1] = B[k-min(m, k/2)-1]:找到,返回其中一个即可。
3.源代码
#include <iostream> #include <algorithm> using namespace std; class MySolution { public: int find_k_min(int A[], int m, int B[], int n, int k) { if (m > n) return find_k_min(B, n, A, m, k); if (m == 0) return B[k-1]; if (k == 1) return min(A[0], B[0]); int pa = min(k/2, m); int pb = k - pa; if (A[pa-1] < B[pb-1]) find_k_min(A + pa, m - pa, B, n, k - pa); else if (A[pa-1] > B[pb-1]) find_k_min(A, m, B + pb, n - pb, k - pb); else return A[pa - 1]; } }; int main(int argc, char const *argv[]) { /* code */ int A[] = {1, 3, 5, 7, 9}; int B[] = {2, 4, 6, 8, 10}; MySolution test; cout << test.find_k_min(A, 5, B, 5, 5) << endl; return 0; }
运行结果就不贴了,心算即可验证:)
相关文章推荐
- Android MotionEvent中getX()和getRawX()的区别
- 脑波设备mindwave介绍
- 《Java从入门到精通》第九章学习笔记
- Valid Number——分情况讨论最经典的题(没细看)——这题必须静下心来好好看看
- Eclipse配色方案插件
- 图片压缩之PNG
- FAT32文件系统
- 安装linux服务器后的优化操作(持续更新)
- 空域滤波与频域滤波
- 更改git远程仓库
- 比特币客户端bitcoind的高级用法
- Adapter中getView方法的陷阱
- Asp.Net Mvc: 应用BindAttribute
- javascript 获取视口的高度和宽度
- Android如何自定义一个View(一)
- Servlet--ServletInputStream类,ServletOutputStream类
- redis 学习笔记(3)-master/slave(主/从模式)
- git 去掉已经暂存的无用文件
- linux对mysql数据库的导入导出操作
- Servlet--ServletInputStream类,ServletOutputStream类