題目意思:給出兩個排好序的數組 ,不妨設為a,b都按升序排列,及k的值,求出第k大的那個元素。
分析這個題目,如果題目沒有時間復雜度的要求,我們可以定義兩個指針i,j分別指向a,b,如果a[i]<b[j]則i++否則
j++,這個記錄下走了多少步,如果==k步,則找到了第k大的元素,復雜度為O(k).
那么如果有復雜度的要求,要求為O(log(len_a+len_b))呢,這個就得好好考慮,怎么利用二分來解決這個問題。
解法一:
假如第k大的數在a中,設置a[mid],那么肯定有b[k-mid-1]<=a[mid]<=b[k-mid],這是由於a中已經有mid個元素<a[mid]了,
則b中肯定還有k-mid - 1個元素小於a[mid],所以我們判斷
若b[k-mid-2]<=a[mid]<=b[k-mid-1], 返回a[mid]
若a[mid] < b[k-mid-2] 說明a[mid]小於第k個元素值,a.low = a.mid + 1
若a[mid] > b[k-mid-1],說明a[mid]大於第k個元素值,a.high = a.mid - 1
結束條件為a.low > a.high 如果未找到,則假設存在於b中,再判斷一次
代碼如下:
View Code
int get_k_from_sorted_array(int* a, int* b, int low, int high, int k, int len)
{
if(low > high)
return -1;
int mid = low + (high - low)/2;
//a中元素個數小於k個,那么k - 2 - mid就可能超出b的下標范圍
if(k - 2 - mid >= len)
return get_k_from_sorted_array(a, b, mid + 1, high, k, len);
if(k - 1 - mid < len)
{
//判斷b數據中是否存在b[k-1-mid]
if(a[mid] >= b[k - mid - 2] && a[mid] <= b[k - mid - 1])
return a[mid];
}
else
{
if(a[mid] >= b[k - mid - 2])
return a[mid];
}
if(a[mid] < b[k - mid - 2])
return get_k_from_sorted_array(a, b, mid + 1, high, k, len);
return get_k_from_sorted_array(a, b, low, mid - 1, k, len);
}
int _func(int* a, int a_len, int* b, int b_len, int k)
{
int rst = 0;
if(a_len + b_len + 2 < k)
return -1;
int p1 = a_len > k - 1 ? k - 1: a_len;
int p2 = b_len > k - 1 ? k - 1: b_len;
rst = get_k_from_sorted_array(a, b, 0, p1, k, 4);
if(-1 == rst)
{
rst = get_k_from_sorted_array(b, a, 0, p2, k, 5);
}
return rst;
}
解法二:
判斷a[mid_a] 與 b[mid_b]的關系
如果a[mida] < b[mid_b]
1)k小於等於mida + midb + 1,那么b數組從mid_b開始就沒有用了,縮小b的搜索范圍
2)k大於mida + midb + 1, 那么a數組從low到mid_a開始就沒用了,縮小a的搜索范圍
3)終止條件是 a搜索完 返回b中元素或者相反
代碼如下:
View Code
int get_k_from_sorted_array2(int* a, int*b, int la, int ha, int lb, int hb, int k)
{
if(la > ha)
return b[lb + k - 1];
if(lb > hb)
return a[la + k - 1];
int mida = (la + ha)>>1;
int midb = (lb + hb)>>1;
int num = mida- la + midb - lb + 1;
cout<<la<<" "<<ha<<" "<<lb<<" "<<hb<<" "<<num<<" "<<a[mida]<<" "<<b[midb]<<endl;
if(a[mida] <= b[midb])
{
if(k <= num)
return get_k_from_sorted_array2(a, b, la, ha, lb, midb - 1, k);
else
return get_k_from_sorted_array2(a, b, mida + 1, ha, lb, hb, k - (mida - la + 1));
}
else
{
if(k <= num)
return get_k_from_sorted_array2(a, b, la, mida - 1, lb, hb, k);
else
return get_k_from_sorted_array2(a, b, la, ha, midb + 1, hb, k - (midb - lb + 1));
}
}
int _func2(int* a, int a_len, int* b, int b_len, int k)
{
int rst = 0;
if(a_len + b_len < k)
return -1;
int p1 = a_len > k ? k : a_len;
int p2 = b_len > k ? k : b_len;
cout<<p1<<" "<<p2<<endl;
rst = get_k_from_sorted_array2(a, b, 0, p1 - 1, 0, p2 - 1, k);
return rst;
}
