中位數是將兩個集合劃分為兩個長度相等的子集,其中乙個子集的元素總是大於另乙個子集中的元素。
設兩個公升序排列的有序陣列a與b,a中包含m個元素,b中包含n個元素,請你找出這兩個有序陣列的中位數,並且要求演算法的時間複雜度為o(log(m + n))。
a[0]………………a[i-1] | a[i]………………a[m-1]
b[0]………………b[j-1] | b[j]………………b[n-1]
記陣列a,b的長度分別為m,n,不妨設m<=n,a,b公升序排列。i,j分別將a,b分成兩個部分。a[i]左側的部分記作left_a,其他記作right_a,同理,b[j]左側的部分記作left_b,其他記作right_b。為保證上述的條件,我們在**中做如下處理:
/
*** 確保a的長度小於等於b的長度 */
int m = a.length;
int n = b.length;
if(m > n)
對於a,b有四種情況:
[1]、m+n是偶數時,m是偶數,n是偶數
[2]、m+n是偶數時,m是奇數,n是奇數
[3]、m+n是奇數時,m是偶數,n是奇數
[4]、m+n是偶數時,m是奇數,n是偶數
現在假設一種理想的情況,令i=m/2,j=(m+n)/2-i,且a[i]>=b[j-1],a[i-1]<=b[j],即left_a+left_b全部小於a[i]和b[j],由i與j的位置可知,對於[1]、[2] ,left_a+left_b=right_a+right_b,對於[3]、[4],left_a+left_b+1=right_a+right_b,因為中位數被放到了右側的部分,此時
對於[1]、[2]兩種情況,中位數
對於[3]、[4]兩種情況,中位數
但實際上如此理想的情況基本不會存在,因此我們需要調整i,j的位置。
當a[i]b[j]時,必然有a[i]>b[j-1],這時,需要減小i。令i=i-1,j=j+1。
調整i,j的位置後,重新判斷是否滿足條件a[i]>=b[j-1],a[i-1]<=b[j]。
所以上述過程可以寫作如下的形式,
1、if a[i]>=b[j-1],a[i-1]<=b[j]
if m+n是偶數
median=(max(a[i-1],b[j-1])+min(a[i],b[j]))/2
if m+n是奇數
min(a[i],b[j])
2、if a[i]b[j]
i=i-1,j=j+1
重複1
while
(i>=0&
&ielse
if(a[i]
)else
if(a[i-1]
>b[j])}
}
當然上面沒有考慮邊界的情況,即i=0和i=m-1時的情況,下面討論邊界的情況。
當i=0時,i-1會超出陣列a的下界,這時我們只需判斷a[i]>=b[j-1]是否成立,若有a[i]>=b[j-1]
if m+n是偶數
median=(b[j-1]+min(a[i],b[j]))/2
if m+n是奇數
median=min(a[i],b[j])
if
(i==0)
}
若a[i]> b[j],這時,i需要繼續減小,i會小於0,出現這種情況時, a中的元素全部大於b中的元素。
當i=m-1時,i-1不會超出下界,只需注意a[m-1]<=b[0]時的情況,當a[m-1]<=b[0]時,a中的元素全部小於b。
我們需要注意j的值是否超過上界或者下界嗎?
當m/**
* 處理a全部大於b或a全部小於b的情況
*/if
(a[0
]>=b[n-1]
) = a[0],min = b[n-1]
return
(a[0
]+ b[n -1]
)/2.0;
}else
}else
}else
if(a[m-1]
<=b[0]
) = a[m-1],min = b[0]
return
(a[m-1]
+ b[0]
)/2.0;
}else
}else
}同時,我們要注意到,要求時間複雜度為o(log(m + n)),所以在增大或者減小i時我們採用二分查詢。我們知道二分查詢的時間複雜度為o(log(2n)),採用二分查詢的方法,時間複雜度為o(log(m))。
if
(a[i]
)else
if(a[i-1]
>b[j]
)
private static double findmediansortedarrays(
int[
] a,
int[
] b)/**
* 處理a全部大於b或a全部小於b的情況
*/if
(a[0
]>=b[n-1]
)= a[0]
,min
= b[n-1]
return
(a[0
]+ b[n -1]
)/2.0;
}else
}else
}else
if(a[m-1]
<=b[0]
)= a[m-1]
,min
= b[0]
return
(a[m-1]
+ b[0]
)/2.0;
}else
}else
}int
max= m;
intmin=0
;int i =
(max
+min)/
2;int j =
(m+n)/2
-i;while
(i>=0&
&i(i-1
>=0)
else
if(a[i]
)else
if(a[i-1]
>b[j])}
}return
0.0;
}
兩個排序陣列的中位數
求兩個排序陣列中位數,這道題是很有意思的一道題目,演算法導論中9.3 8題,這題必須在o logn 的時間複雜度求解,否則肯定悲劇。這題有個關鍵的條件,那就是這兩個陣列長度相等 思路如下 陣列a 1,3,5,7,9 陣列b 2,4,6,8,10 首先取二者的中位數,在o 1 時間複雜度內求出,那麼陣...
兩個排序陣列的中位數
求兩個排序陣列中位數,這道題是很有意思的一道題目,演算法導論中9.3 8題,這題必須在o logn 的時間複雜度求解,否則肯定悲劇。這題有個關鍵的條件,那就是這兩個陣列長度相等 思路如下 陣列a 1,3,5,7,9 陣列b 2,4,6,8,10 首先取二者的中位數,在o 1 時間複雜度內求出,那麼陣...
兩個排序陣列的中位數
兩個排序的陣列a和b分別含有m和n個數,找到兩個排序陣列的中位數,要求時間複雜度應為o log m n 給出陣列a 1,2,3,4,5,6 b 2,3,4,5 中位數3.5 給出陣列a 1,2,3 b 4,5 中位數 3 public double findmediansortedarrays in...