【劍指Offer】37、數字在排序數組中出現的次數


  題目描述:

  統計一個數字在排序數組中出現的次數。例如,輸入排序數組{1,2,3,3,3,3,4,5}和數字3,由於數字3在該數組中出現了4次,所以函數返回4。

  解題思路:

  既然輸入的數組是有序的,所以我們就能很自然的想到用二分查找算法。以題目中給的數組為例,一個比較自然的想法是用二分查找先找到一個3,由於要計算的是輸出的次數,所以需要在找到的這個3的左右兩邊分別再進行順序掃描,進而得到3的個數,這樣最壞的情況下時間復雜度仍然是O(n),和直接順序掃描的效率相同。

  因此,需要考慮怎樣更好的利用二分查找算法,由於數組有序,如果知道了第一個k出現的位置和最后一個k出現的位置,那么我們就可以直接算出有多少個k。因此將思路轉化為通過二分查找求第一個和最后一個k出現的位置。

  以第一個k出現的位置為例,利用二分查找算法可以直接對數組進行二分,而每次總是拿中間的數字和k做比較,如果中間的數字大於k,那么第一個k只有可能出現在左邊,下一次直接在數組左半段繼續進行二分查找;如果中間的數字小於k,則第一個k只有可能出現在右邊,則在右半段再查找;如果中間的數字等於k,我們先判斷它前面的一個數字是不是k,如果不是,那么這個中間的數字就是第一個出現的位置,反之,如果中間數字前面的數字是k,那么第一個k仍然在前半段,繼續查找。

  同理,找最后一個k出現的位置方法類似,可以使用兩個函數分別獲得。

  編程實現(Java):

public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        int first=getFirstIndex(array,k);
        int last=getlastIndex(array,k);
        if(first==-1 || last==-1)
            return 0;
        return last-first+1;
    }
    //二分查找
    public int getFirstIndex(int[] array,int k){
        int res=-1;
        if(array==null||array.length==0)
            return res;
        int low=0,high=array.length-1;
        while(low<=high){ //要有=
            int mid=low+(high-low)/2;
            if(array[mid]<k)
                low=mid+1;
            else if(array[mid]>k)
                high=mid-1;
            else { //相等
                mid=mid-1;
                if(mid<low || array[mid]!=k)
                    return mid+1;
                else 
                    high=mid;
            }
        }
        return res;
    }
    
    public int getlastIndex(int[] array,int k){
        int res=-1;
        if(array==null||array.length==0)
            return res;
        int low=0,high=array.length-1;
        while(low<=high){ //要有=
            int mid=low+(high-low)/2;
            if(array[mid]<k)
                low=mid+1;
            else if(array[mid]>k)
                high=mid-1;
            else { //相等
                mid=mid+1;
                if(mid>high || array[mid]!=k)
                    return mid-1;
                else 
                    low=mid;
            }
        }
        return res;
    }
}


免責聲明!

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



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