兩個有序數組,找第k小的數//未完


1、題目描述:a,b兩個有序數組,找出第k小的數,logk,二分查找,1個小於怎么辦?

2、思路:

時間復雜度為O(log(m+n)),自然想到可能會用二分法

假設A 和B 的元素個數都大於k/2,我們將A 的第k/2 個元素(即A[k/2-1])和B 的第k/2個元素(即B[k/2-1])進行比較,有以下三種情況(為了簡化這里先假設k 為偶數,所得到的結論對於k 是奇數也是成立的):
• A[k/2-1] == B[k/2-1]
• A[k/2-1] > B[k/2-1]
• A[k/2-1] < B[k/2-1]

如果A[k/2-1] < B[k/2-1],意味着A[0] 到A[k/2-1] 的肯定在A 與B 的所有元素的前k個元素的范圍內,也就是說,A的前(k/2-1)個元素中不可能存在大於A與B所有元素的第k小元素。

因此,我們可以放心的刪除A 數組的這k/2 個元素。同理,當A[k/2-1] > B[k/2-1] 時,可
以刪除B 數組的k/2 個元素。
當A[k/2-1] == B[k/2-1] 時,說明找到了第k 大的元素,直接返回A[k/2-1] 或B[k/2-1]
即可。

因此,我們可以寫一個遞歸函數。那么函數什么時候應該終止呢?
• 當k=1 是,返回min(A[0], B[0]);
• 當A[k/2-1] == B[k/2-1] 時,返回A[k/2-1] 或B[k/2-1]

但是可能出現如果A中有3個元素,B中有12個元素,我們要找A與B所有元素的第8小元素,這時m < k/2
當出現這種情況時,我們可以取A中的所有元素,取B中的前k-m個元素
也可以按比例來取,比如取A中的前(m/(m+n))*k個元素,取B中前(k-(m/(m+n))*k)個元素

3、代碼:

public class Solution {
    public static void main(String[] args) {
        //定義兩個有序數組a,b
        int[] a = new int[]{1,9,10,18};
        int[] b = new int[]{7,10};

        //查找兩個數組的第k小元素
        int k = 5;
        System.out.println(Search(a,0,a.length-1,b,0,b.length-1,k));

    }

    public static int Search(int[] a,int startA,int endA,int[] b,int startB,int endB,int k){
        if(k == 1){
            if(a[startA] <= b[startB]){
                return a[startA];
            }else{
                return b[startB];
            }
        }

        //如果startA>endA,則說明A中的元素已經排除完,只剩下B中元素,此時只要取B中前k個元素就好
        if(startA > endA){
            return b[startB + k - 1];
        }
        //同上
        if(startB > endB){
            return a[startA + k -1];
        }

        int al = endA - startA + 1;
        int bl = endB - startB + 1;

        //如果a中元素個數大於b中元素個數,此時應該將a與b的位置交換,將元素少的數組放在前面,這是為了57行代碼的判斷
        if(al > bl){
            return Search(b,startB,endB,a,startA,endB,k);
        }

        int ms = 0;
        int ns = 0;

        //如果a中元素個數<k/2,此時應該取a中的所有元素,如果不做49的行的處理的話,可能會造成數組溢出
        if((endA - startA + 1) < k/2){
            ms = endA - startA + 1;
        }else{
            ms = k/2;
        }

        ns = k - ms ;

        int m = ms-1 + startA;
        int n = ns-1+ startB;

        if(a[m] == b[n]){
            return a[m];
        }else if(a[m] > b[n]){
            return Search(a,startA,m,b,n+1,endB,k-ns);
        }else{
            return Search(a,m+1,endA,b,startB,n,k-ms);
        }

    }

}

 

 

 

參考博客:https://blog.csdn.net/peach90/article/details/45599843


免責聲明!

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



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