方法一:以空間換時間,可以定義一個計數數組int count[101],用來對數組中數字出現的次數進行計數(只能針對數組中數字的范圍1~100),count數組中最大的元素對應的下標,即為出現次數最多的那個數。Java代碼如下:
public class SearchMuch { public static void candidate (int[] array) // 找出數組中出現次數最多的那個數 { int[] count = new int[101]; // 計數數組,每個元素的默認值為0 for(int i = 0; i < array.length; i++) { count[array[i]]++; // 對應的計數值加1 } int maxCount = count[0]; int maxNumber = 0; for(int i = 1; i < 100; i++) // 找出最多出現的次數 { if(count[i] > maxCount) maxCount = count[i]; } for(int i = 0; i < 100; i++) // 找出出現最多次的那個數字 { if(count[i] == maxCount) maxNumber = i; } System.out.println("出現次數最多的數字為:" + maxNumber); System.out.println("該數字一共出現" + maxCount + "次"); } }
上例是一種典型的空間換時間算法(所需數組空間的大小完全取決於數組中數字的大小)。一般情況下,除非內存空間足夠大且數組中的數不是很大,否則一般不采用這種方法。
方法二:使用HashMap,每個Entry的key存放數組中的數字,value存放該數字出現的次數,首先遍歷數組元素構造HashMap,然后遍歷每個Entry,找出最大value對應的key,即是出現次數最多的那個數。此算法的時間復雜度為O(n)。Java代碼如下:
public class SearchMuch { public static void candidate (int[] array) // 找出數組中出現次數最多的那個數 { // map的key存放數組中的數字,value存放該數字出現的次數 HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); for(int i = 0; i < array.length; i++) { if(map.containsKey(array[i])) { int formerValue = map.get(array[i]); map.put(array[i], formerValue + 1); // 該數字出現的次數加1 } else { map.put(array[i], 1); // 該數字第一次出現 } } Collection<Integer> count = map.values(); // 找出map的value中最大值,也就是數組中出現最多的數字所出現的次數 int maxCount = Collections.max(count); int maxNumber = 0; for(Map.Entry<Integer, Integer> entry : map.entrySet()) { //得到value為maxCount的key,也就是數組中出現次數最多的數字 if(entry.getValue() == maxCount) { maxNumber = entry.getKey(); } } System.out.println("出現次數最多的數字為:" + maxNumber); System.out.println("該數字一共出現" + maxCount + "次"); } }
方法三(針對出現次數超過一半的情況):可以用數對對消的思路假設數組如下{1, ?, 1, 1, 1, ?, 1, ?, ?},數組中?代表其他任意不為1的數字,顯然,出現次數最多的數為1,且超過了一半,我們可以把1與?匹配(當然,我們事先並不知道1就是出現次數最多的那個數,這里只是講可行的思路),一次匹配出一個<1,?>,最后剩余沒得到匹配的數還是1,就是超過一半的次數,代碼有時間再寫。
方法四(針對出現次數超過一半的情況):利用快速排序的分割算法(partition)。任意選取一個基准pivot,調用partition()把數組分成兩個部分,小於pivot的部分和大於pivot的部分,而pivot就位於它們之間,把返回的pivot的索引與數組的中位索引middle進行比較,只要二者不相等就更新邊界:
while(pivot_index != middle) { if (pivot_index < middle) left = pivot_index + 1; else right = pivot_index - 1; pivot_index = partition(A, left, right); }
最后A[middle]必定就是數組A中出現次數超過一半的那個數
方法五(針對出現次數超過一半的情況):蒙特卡羅算法
