8.7在陣列中找出出現次數大於N÷K的數
阿新 • • 發佈:2018-12-23
題目
給定一個整形陣列arr,再給定一個整數K,列印所有出現次數大於N/K的數,如果沒有這樣的數,列印提示資訊。
首先分析K=2這個特殊情況,有以下思路:
-
排序後,取陣列中間的數。但該方法的時間複雜度為排序演算法的時間複雜度O(NlogN)。
-
一次在陣列中刪掉兩個不同的數,不停地刪除,直到剩下的數只有一種,一定是那個出現次數大於一半的數。
實現程式碼:
/** * 特例:找出出現次數大於一半的數 * * @param arr 待查陣列 */ public void printHalfMajor (int[] arr) { int
拓展思路二,回到K為不定項的情況,類似地,只需要立K-1個候選,然後有K-1個times統計即可。
程式碼實現如下:
public void printKMajor(int[] arr, int K) {
if (K < 2) {
System.out.println("The value of K is invalid.");
return;
}
HashMap<Integer, Integer> cands = new HashMap<>();
for (int i = 0; i != arr.length; i++) {
if (cands.containsKey(arr[i])) {
cands.put(arr[i], cands.get(arr[i]) + 1);
} else {
if (cands.size() == K - 1) { //候選滿了
allCandsMinusOne(cands);
} else {
cands.put(arr[i], 1);
}
}
}
//驗證
HashMap<Integer, Integer> reals = getReals(arr, cands);
boolean hasPrint = false;
for (Map.Entry<Integer, Integer> set : cands.entrySet()) {
Integer key = set.getKey();
if (reals.get(key) > arr.length / K) {
hasPrint = true;
System.out.println(key + " ");
}
}
System.out.println(hasPrint ? "" : "No such number.");
}
/**
* 每一個候選的點數都減一,並剔除減後點數為0的候選
*
* @param map 所有候選
*/
public void allCandsMinusOne(HashMap<Integer, Integer> map) {
List<Integer> removeList = new LinkedList<>();
for (Map.Entry<Integer, Integer> set : map.entrySet()) {
Integer key = set.getKey();
Integer value = set.getValue();
if (value == 1) {
removeList.add(key);
}
map.put(key, value - 1);
}
for (Integer removeKey : removeList) {
map.remove(removeKey);
}
}
/**
* 得到所有候選的出現次數
*
* @param arr 原陣列
* @param cands 所有候選
* @return map<候選數 , 出現次數>
*/
public HashMap<Integer, Integer> getReals(int[] arr,
HashMap<Integer, Integer> cands) {
HashMap<Integer, Integer> reals = new HashMap<>();
for (int i = 0; i != arr.length; i++) {
int curNum = arr[i];
if (cands.containsKey(curNum)) {
if (reals.containsKey(curNum)) {
reals.put(curNum, reals.get(curNum) + 1);
} else {
reals.put(curNum, 1);
}
}
}
return reals;
}