兩個有序數組中查找第K大數


題目:兩個數組A、B,長度分別為m、n,即A(m)、B(n),分別是遞增數組。求第K大的數字。
 
方法一:
簡單的辦法,使用Merge Sort,首先將兩個數組合並,然后在枚舉查找。這個算法的時間復雜度是O(m+n)、空間復雜度也是O(M+n)。
這個方法其實沒有考慮到有第K大數為兩個相同數字的情況。
 
方法二:
這里需要兩個前提條件,
1、如果K是中位數,則(M+n)是奇數還是偶數是有關系的。如果是奇數,那么中位數唯一,如果是偶數就有兩個中位數,可以隨便取一個。
2、如果找到的第K大數是x,假如在A的位置是A(x),在B中的位置是B(x),則Ax+Bx-1=k是成立的。
 
接下來是具體實現邏輯:
1、首先假設K大數在A數組中,首先檢查 (m/(m+n))*(k-1),假設其值為A1。然后檢查B中(k+1-(n/(m+n))*(k-1))假設為B1,檢查A1、B1是否相等,或者大於B中的第(k+1-(n/(m+n))*(k-1)),並且小於(k+1-(n/(m+n))*(k-1))+1個元素。滿足條件就可以知道A1就是所求,否則看條件2。
2、如果兩個條件都不滿足,那么需要判斷第K個元素是位於A1左邊還是右邊。
 
如果A1>B1,那么K肯定不在A[0, (m/(m + n)) * (k - 1)]以及B[(k + 1 - (m/(m + n)) * (k - 1))+ 1, n]中;
如果A1<B1,那么K肯定不在A[ (m/(m + n)) * (k - 1), m]以及B[0, (k + 1 - (m/(m + n)) * (k - 1))]中。
 
第K個元素有可能在B中,同理可以假設在B中,再進行一次搜索。復雜度為log(m)+log(n)。
 
具體代碼如下:
int kthsmallest(int *a,int m,int *b,int n,int k) {
        if (m == 0) {
            return b[k - 1];
        }
        if (n == 0) {
            return a[k - 1];
        }
        if (k == 1) {
            return (a[0] < b[0])?a[0]:b[0];
        }
        if (k == m + n) {
            return (a[m - 1] > b[n - 1])?a[m - 1]:b[n - 1];
        }
        int i = ((double) m) / (m + n) * (k - 1);
        int j = k - 1 - i;
        if (j >= n) {
            j = n - 1;
            i = k - n;
        }
        if (((i == 0) || (a[i - 1] <= b[j])) && (b[j] <= a[i])) {
            return b[j];
        }
        if (((j == 0) || (b[j - 1] <= a[i])) && (a[i] <= b[j])) {
            return a[i];
        }
        if (a[i] <= b[j]) {
            return kthsmallest(a + i + 1, m - i - 1, b, j, k - i - 1);
        } else {
            return kthsmallest(a, i, b + j + 1, n - j - 1, k - j - 1);
        }
 
    }
 
 
方法三:
當然也可以在方法一的基礎上,采用一些二分的辦法進行優化,但是這種算法
 
 
參考資料:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM