Java--给定两个有序的数组,长度分别为m和n,求这两个数组中的第K个元素。
首先想到的是,最普通的算法,比较两个数组,碰到较小的计数器加1,并指向下一个,直到计数等于k。算法复杂度O(m+n);
这是一种会被面试官鄙视的算法。,我也用这个方法,被鄙视过。看完这个方法,在进行优化。
package ppp;
public classaa4 {
public static void main(String[] args) {
int[] aa ={2,5,9,77,88,654,854,999};
int[] bb ={3,4,6,8,9,12,52,74,68,881,885};
System.out.println(find(aa,bb,6));
}
public static int find(int[] aa,int[] bb,int k){
int num=0,i=0,j=0;
int[]cc = new int[aa.length+bb.length];
while(i<aa.length && j<bb.length){
if(aa[i]<=bb[j]){
num++;
i++;
if(num==k){
return aa[i-1];
}
}else{
num++;
j++;
if(num==k){
return bb[j-1];
}
}
}
while(i<aa.length && num<k){
num++;
i++;
if(num==k){
return aa[i-1];
}
}
while(j<bb.length && num<k){
num++;
j++;
if(num==k){
return bb[j-1];
}
}
return 0;
}
}
优化的算法是利用中位数,数组A和B,不妨设aMid<bMid,此时,bMid左侧有aMid+bMid+1个元素,如果k< aMid+bMid+1,则所要寻找的第k个数必在bMid的左边,所以bMid之后的元素不可能出现要找的数,所以可以排除掉B数组的后半部分。
如果k> aMid+bMid+1,则所要寻找的第k个数必在bMid的右边,所以bMid左边的元素不可能出现要找的数,而aMid左半边元素必然出现在bMid的左边,所以可以排除掉A数组左半边的元素。
综上所述,对于 k <= aMid+bMid+1 还是 k > aMid+bMid+1 我们都提出了解决的方案,并且每种方案都能把 A 或者 B 的规模减小一半。减小了一半之后,我们将其作为一个新的问题继续使用上面的算法处理,直到 A 或者 B 减小到足够小:
1. A 没有了,这样只需要找出 B 中第 k 大的元素,也就是 B[k]。
2. B 没有了,同上结果就是 A[k]。
3. package ppp;
4. public class aa5 {
5. private int[] aa;
6. private int[] bb;
7. public static void main(String[] args) {
8. aa5 a = new aa5();
9. a.aa = newint[] {2,5,9,77,88,654,854,999};
10. a.bb = newint[] {3,4,6,8,9,12,52,74,68,881,885};
11. System.out.println(a.find(0,a.aa.length-1,0,a.bb.length-1,7));
12. }
13. public int find(int aLeft,int aRight,int bLeft,int bRight,int k){
14.
15. int aMid = (aLeft+aRight)/2;
16. int bMid = (bLeft+bRight)/2;
17.
18. if(aLeft<aRight){
19. returnbb[bLeft+k-1];
20. }
21. if(bLeft<bRight){
22. returnaa[aLeft+k-1];
23. }
24. if(aa[aMid]<=bb[bMid]){
25. if(k<=aMid-aLeft+bMid-bLeft+1){
26. returnfind(aLeft,aRight,bLeft,bMid-1,k);
27. }else{
28. returnfind(aMid+1,aRight,bLeft,bRight,k-(aMid-aLeft)-1);
29. }
30. }else{
31. if(k<=aMid-aLeft+bMid-bLeft+1){
32. returnfind(aLeft,aMid-1,bLeft,bRight,k);
33. }else{
34. returnfind(aLeft,aRight,bMid+1,bRight,k-(bMid-bLeft)-1);
35. }
36. }
37. }
38. }