劍指offer第二版-39.數組中出現次數超過一半的數字

本系列導航:劍指offer(第二版)java實現導航帖

面試題39:數組中出現次數超過一半的數字

題目要求:
找出數組中出現次數超過數組長度一半的數字。如輸入{1,2,3,2,2,2,5,4,2},則輸出2。

解題思路:
因為該數字的出現次數超過了數組長度的一半,因此可以將問題轉化為求數組的中位數。如果按照這個思路,有以下兩種方式解決:排序后求中位數、用快排的分區函數求中位數(topK問題),這兩種思路都比較簡單,此處不再贅述。
書中還提到一種思路,相當巧妙,可以看作一種特殊的緩存機制。該思路需要一個整型的value變量和一個整型的count變量,記錄緩存值與該緩存值被命中的次數。緩存規則以及執行步驟如下:

步驟1: 緩存值value,命中次數count均初始化為0。
步驟2: 從頭到尾依次讀取數組中的元素,判斷該元素是否等于緩存值:
     步驟2.1:如果該元素等于緩存值,則命中次數加一。
     步驟2.2:如果該元素不等于緩存值,判斷命中次數是否大于1:
              步驟2.2.1:如果命中次數大于1,將命中次數減去1。
              步驟2.2.2:如果命中次數小于等于1,則令緩存值等于元素值,命中次數設為1
步驟3: 最終的緩存值value即為數組中出現次數超過一半的數字。

此方法時間復雜度o(n),空間復雜度o(1),實現簡單。

package chapter5;

/**
 * Created with IntelliJ IDEA.
 * Author: ryder
 * Date  : 2017/7/28
 * Time  : 17:51
 * Description: 數組中出現次數超過一半的數字
 **/
public class P205_MoreThanHalfNumber {
    //轉化為topK問題(此處求第k小的值),使用快排的分區函數解決,求第targetIndex+1小的數字(下標為targetIndex)
    //書中說這種方法的時間復雜度為o(n),但沒懂為什么。網上也有人說為o(nlogk)
    public static int moreThanHalfNum1(int[] data){
        if(data==null || data.length==0)
            return 0;
        int left = 0,right=data.length-1;
        //獲取執行分區后下標為k的數據值(即第k+1小的數字)
        int k = data.length>>>1;
        int index = partition(data,left,right);
        while(index!=k){
            if(index>k)
                index = partition(data,left,index-1);
            else
                index = partition(data,index+1,right);
        }
        return data[k];
    }
    //分區,[小,povot,大]
    public static int partition(int[] data,int left,int right){
        int pivot = data[left];
        while(left<right){
            while (left<right && data[right]>=pivot)
                right--;
            if(left<right)
                data[left] = data[right];
            while (left<right && data[left]<pivot)
                left++;
            if(left<right)
                data[right] = data[left];
        }
        data[left] = pivot;
        return left;
    }

    //根據數組特點進行記錄、查找,時間復雜度o(n)
    public static int moreThanHalfNum2(int[] data){
        if(data==null || data.length==0)
            return 0;
        int count = 1;
        int value = data[0];
        for(int i=1;i<data.length;i++){
            if(data[i]==value)
                count++;
            else if(data[i]!=value && count==1)
                value = data[i];
            else
                count--;
        }
        return value;
    }
    public static void main(String[] args){
        int[] data = {1,2,3,2,2,2,5,4,2};
        System.out.println(moreThanHalfNum2(data));
        System.out.println(moreThanHalfNum1(data));
    }
}

運行結果

2
2
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容