求兩個中位數

問題:設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;
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章