2014-05-06 11:31
原题:
Find the k-th Smallest Element in Two Sorted Arrays. I followed the algorithm from this post, http://leetcode.com/2011/01/find-k-th-smallest-element-in-union-of.html But it does not handle the case where there are duplicates? Does anyone know how to do that? Also, in Java, how should we reduce the size of the arrays? I used the code below, but did not work.
题目:给定长度为n和m的两个有序数组,找出两数组合并后第K小的数,即升序排第K位的数。
解法1:又是这位“Guy”老兄发的题目,连链接都给贴出来了,明摆着告诉别人这题是他从别处copy来的。不得不说,这道题是非常具有区分度的一道简单题/难题。简单的做法,自然是O(K)时间的算法,在归并过程中就可以得出第K小的元素。
代码:
1 // http://www.careercup.com/question?id=6283958983589888 2 #include <algorithm> 3 #include <cstdio> 4 #include <vector> 5 using namespace std; 6 7 int findKthSmallest(vector<int> &a, vector<int> &b, int k) 8 { 9 int na, nb; 10 11 na = (int)a.size(); 12 nb = (int)b.size(); 13 if (na == 0) { 14 return b[k]; 15 } else if (nb == 0) { 16 return a[k]; 17 } else if (a[0] > b[nb - 1]) { 18 return (k < nb ? b[k] : a[k - nb]); 19 } else if (b[0] > a[na - 1]) { 20 return (k < na ? a[k] : b[k - na]); 21 } 22 23 int i, j; 24 25 i = j = 0; 26 int res = a[i] < b[j] ? a[i++] : b[j++]; 27 while (i + j <= k) { 28 if (i == na) { 29 res = b[j++]; 30 } else if (j == nb) { 31 res = a[i++]; 32 } else { 33 res = a[i] < b[j] ? a[i++] : b[j++]; 34 } 35 } 36 37 return res; 38 } 39 40 int main() 41 { 42 vector<int> a, b; 43 int na, nb; 44 int i; 45 46 while (scanf("%d%d", &na, &nb) == 2 && (na > 0 && nb > 0)) { 47 a.resize(na); 48 b.resize(nb); 49 for (i = 0; i < na; ++i) { 50 scanf("%d", &a[i]); 51 } 52 for (i = 0; i < nb; ++i) { 53 scanf("%d", &b[i]); 54 } 55 while (scanf("%d", &i) == 1) { 56 printf("%d\n", findKthSmallest(a, b, i)); 57 } 58 a.clear(); 59 b.clear(); 60 } 61 62 return 0; 63 }
解法2:这个代码不是我独立写出的,在参考了这篇文章的思路以后,模仿写了一版代码。此算法的复杂度应该是O(log(k))的,文章中说是O(log(n) + log(m))。解法中有个比较关键的思想,i + j = k - 1。如果某个a[i]恰好夹在b[j - 1]和b[j]之间,那么a[i]一定排在归并结果的第i + j + 1位,也就是第k位(从1算起)。反过来b[j]夹在a[i - 1]和a[i]之间道理也是一样的。理解这个道理一开始让我费了一番功夫,理解代码里的各种条件表达式则是另一番功夫了。
代码:
1 // http://www.careercup.com/question?id=6283958983589888 2 #include <algorithm> 3 #include <climits> 4 #include <cstdio> 5 #include <vector> 6 using namespace std; 7 8 int findKthSmallest(vector<int> &a, vector<int> &b, int na, int nb, int ia, int d, int k) 9 { 10 int ib = k - 1 - ia; 11 12 int pre_a = ia == 0 ? INT_MIN : a[ia - 1]; 13 int pre_b = ib == 0 ? INT_MIN : b[ib - 1]; 14 int cur_a = ia == na ? INT_MAX : a[ia]; 15 int cur_b = ib == nb ? INT_MAX : b[ib]; 16 17 if (cur_a >= pre_b && cur_a <= cur_b) { 18 return cur_a; 19 } 20 if (cur_b >= pre_a && cur_b <= cur_a) { 21 return cur_b; 22 } 23 24 if (cur_a > cur_b) { 25 ia = (k - 1) - (ia - d) > nb ? (k - 1) - nb : ia - d; 26 } else { 27 ia = ia + d > na ? na : ia + d; 28 } 29 30 return findKthSmallest(a, b, na, nb, ia, (d + 1) / 2, k); 31 } 32 33 int main() 34 { 35 vector<int> a, b; 36 int na, nb; 37 int i; 38 int ia; 39 40 while (scanf("%d%d", &na, &nb) == 2 && (na > 0 && nb > 0)) { 41 a.resize(na); 42 b.resize(nb); 43 for (i = 0; i < na; ++i) { 44 scanf("%d", &a[i]); 45 } 46 for (i = 0; i < nb; ++i) { 47 scanf("%d", &b[i]); 48 } 49 while (scanf("%d", &i) == 1) { 50 ia = min(na, i - 1); 51 printf("%d\n", findKthSmallest(a, b, na, nb, ia, (ia + 1) / 2, i)); 52 } 53 a.clear(); 54 b.clear(); 55 } 56 57 return 0; 58 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)