计算两个有序数组的第K大数(转)
-
传统解法,最直观的解法是O(m+n)。直接merge两个数组,然后求第K大的数字。
-
如果想要时间复杂度将为O(log(m+n))。我们可以考虑从K入手。如果我们每次能够删除一个一定在第K个元素之前的元素,那么我们需要进行K次,但是如果每次我们都删除一半呢?由于两个数组都是有序的,我们应该充分利用这个信息。
- 假设A B 两数组的元素都大于K/2,我们将A B两数组的第K/2个元素进行比较。比较的结果有三种情况。
- A[K/2] == B[K/2]
- A[K/2] > B[K/2]
- A[K/2] <= B[K/2]
- 如果 A[K/2] < B[K/2] 意味着 A[0] 到 A[K/2] 肯定在A∪B的前k个元素中。因此我们可以放心删除A数组的这个k/2个元素。同理A[K/2] > B[K/2]。
- 如果 A[K/2] == B[K/2] 说明已经找到了第K个元素,直接返回A[K/2]或者B[K/2]。
- 假设A B 两数组的元素都大于K/2,我们将A B两数组的第K/2个元素进行比较。比较的结果有三种情况。
-
代码如下
1 int find_kth(int A[],int m, int B[], int n, int k){ 2 if(m > n ) 3 return find_kth(B, n, A, m, k); 4 if( m == 0) 5 return B[k-1]; 6 if( k == 1) 7 return min(A[0], B[0]); 8 9 int ia = min(k /2, m); 10 int ib = k -ia; 11 if( A[ia-1] < B[ib -1]){ 12 return find_kth(A +ia, m -ia, B, n, k -ia); 13 }else if( A[ia-1] > B[ib-1]){ 14 return find_kth(A, m, B +ib, n -ib, k -ib); 15 }else 16 return A[ia-1]; 17 }
说明
- 注意其中的递归终止条件。
- 将求第K大元素的问题划分成为子问题,不断的对问题进行缩小,采取递归的方式求解。
- 此问题可以进行拓展,比如求两有序数组的中位数。
联系方式:emhhbmdfbGlhbmcxOTkxQDEyNi5jb20=
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了