問題:設X[0:n-1]和Y[0:n-1]爲兩個數組,每個數組中含有n個已排好序的數。試設計一個O(logn)時間算法,找出X和Y的2n個數的中位數並輸出。
問題分析:本來可以很簡單的排序(O(n))輸出中間兩個數的,但是題目要求複雜度要O(logn),就有點麻煩了。主要就是對兩個數組不斷進行刪除裁剪(這裏說的刪除裁剪並不是真的對數組元素進行刪除,只是進行範圍的縮小),直到X數組和Y數組只剩下兩個元素,然後對這四個元素進行比較選出中位數。
具體方法:new兩個數組X[]和Y[],然後用兩個for循環進行初始化,接着用while循環進行縮小範圍的操作,直到X和Y數組都只剩下兩個元素。
while循環的內部操作:1判斷X數組和Y數組是否只有兩個元素,如果是的話,比較X[xleft]和Y[yleft]的大小,取大者爲第一個中位數;然後比較X[xright]和Y[yright]的大小,取小的作爲第二個中位數。2否則就比較X[xmid]和Y[ymid]的大小。1)如果X[xmid]<Y[ymid],則刪除xmid左邊的全部元素,同時刪除Y數組的右邊同個數的元素。注意一下對yright的賦值問題,因爲如果Y數組元素個數這時是偶數的話,yright=ymid+1;否則就yright=ymid。2)如果X[xmid]>Y[ymid],則刪除xmid右邊的全部元素,同時刪除Y數組的左邊同個數的元素。也一樣要注意一下對yleft的賦值問題。
以下是Java代碼
import java.util.Scanner;
public class ZhongWeiShu {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("請帥哥輸入數組的元素個數:");
Scanner input=new Scanner(System.in);
int n=input.nextInt();
//根據輸入的數字n來創建兩個數組X[]和Y[]
int[] x=new int[n];
int[] y=new int[n];
System.out.println("請輸入第一個數組元素:");
for(int i=0;i<n;i++){
x[i]=input.nextInt();
}
System.out.println("請輸入第二個數組元素:");
for(int i=0;i<n;i++){
y[i]=input.nextInt();
}
input.close();
//調用函數findZhongWeiShu()來輸出中位數
findZhongWeiShu(x,y,n);
}
public static int findZhongWeiShu(int x[],int y[],int n){
int xleft=0,xright=n-1,yleft=0,yright=n-1;
//使用while(true)來無限循環直到break中斷
while(true){
/*當X數組和Y數組都只剩下兩個元素的時候
* 這時剩下四個數字,取xleft和yleft的較大者作爲第一個中位數
* 取xright與yright地較小者作爲第二個中位數
*/
if((xright-xleft)==1&&(yright-yleft)==1){
System.out.println("帥哥你的中位數是:");
System.out.println(((x[xleft]>=y[yleft])?x[xleft]:y[yleft])+" "+
((x[xright]<=y[yright])?x[xright]:y[yright]));
break;
}
else{
int xmid=(xleft+xright)/2;
int ymid=(yleft+yright)/2;
//比較X[xmid]跟Y[ymid]的大小
//如果相等說明這兩個數都是中位數
if(x[xmid]==y[ymid]){
System.out.println("帥哥你的中位數是:");
System.out.println(x[xmid]+" "+x[xmid]);
break;
}
/*如果小於,則“刪除”X數組左邊全部元素,同時也要刪除Y數組
* 從右邊數過來和X數組刪除的相同個數的元素
*/
else if(x[xmid]<y[ymid]){
//計算Y數組剩下的元素個數是否是偶數
if((yleft+yright+1)%2==0){
xleft=xmid;
yright=ymid+1;
}
else{
xleft=xmid;
yright=ymid;
}
}
else{
/*如果大於,則“刪除”X數組右邊全部元素,同時也要刪除Y數組
* 從左邊數過來和X數組刪除的相同個數的元素
*/
if((xright+xleft+1)%2==0){
xright=xmid+1;
yleft=ymid;
}
else{
xright=xmid;
yleft=ymid;
}
}
}
}
return 0;
}
}