劍指 offer程式碼解析——面試題29陣列中出線次數超過一半的數字
阿新 • • 發佈:2022-05-03
題目:陣列中有一個數字出現的次數超過陣列長度的一半,請找出這個數字。
分析:本題最直觀的思路就是分別統計陣列中每個數出現的次數,然後求出最大值,判斷是否超過陣列長度的一半。這種方法的時間複雜度為O(n^2),在面試中,第一反應想到的方法往往不是最佳答案,下面我們來尋求更加高效的方式。
一個數出現的次數如果超過陣列長度的一半,那麼可以得出以下結論:
1.如果把超過陣列長度一半的數整理在一起形成陣列b,那麼不管把b放在陣列的什麼位置,陣列的中位數一定在b中。
2.個數超過陣列長度一半的數最多隻有一個。
基於上述兩點結論,我們可以首先將陣列排序,使得超過陣列長度一半的那些數靠在一起,然後取排序後陣列的中位數,最後判斷該數的長度是否超過陣列長度的一半。程式碼如下:
import offer8.QuickSort; /** * 題目:陣列中有一個數字出現的次數超過陣列長度的一半,請找出這個數字。 * @author 大閒人柴毛毛 * @date 2016年3月16日 */ public class CountNumber { /** * 分析:本題最直觀的思路就是分別統計陣列中每個數出現的次數,然後求出最大值,判斷是否超過陣列長度的一半。 * 這種方法的時間複雜度為O(n^2),在面試中,第一反應想到的方法往往不是最佳答案,下面我們來尋求更加高效的方式。 */ /** * 一個數出現的次數如果超過陣列長度的一半,那麼可以得出以下結論: * 1.如果把超過陣列長度一半的數整理在一起形成陣列b,那麼不管把b放在陣列的什麼位置,陣列的中位數一定在b中。 * 2.個數超過陣列長度一半的數最多隻有一個。 * 基於上述兩點結論,我們可以首先將陣列排序,使得超過陣列長度一半的那些數靠在一起,然後取排序後陣列的中位數,最後判斷該數的長度是否超過陣列長度的一半。 * 程式碼如下: */ /** * 獲取陣列中出現次數超過一半的那個數 * @param a 輸入的陣列 * @return 返回出現次數超過一半的那個數(返回-1表示函數出錯) */ public static int countNumber(int[] a){ //若陣列為空 if(a==null || a.length<=0){ System.out.println("陣列為空!"); return -1; } //對陣列排序 QuickSort.QuickSort(a); //獲取中位數 int mid = a[a.length/2]; //計算中位數出現的次數 int count = 0; for(int i=0;i<a.length && a[i]<=mid;i++){ if(a[i]==mid) count++; } //判斷中位數出現的次數是否超過陣列長度的一半 if(count>=a.length/2) return mid; else return -1; } /** * 測試 */ public static void main(String[] args){ int[] a = {3,1,3,2,3,2,3,2,2,3,5,3,4,2,3,3}; System.out.println(countNumber(a)); } }