版权声明:本文采用 知识共享署名4.0 国际许可协议进行许可。 https://blog.csdn.net/youmian6868/article/details/85200059
题目
给定一个整形数组arr,再给定一个整数K,打印所有出现次数大于N/K的数,如果没有这样的数,打印提示信息。
首先分析K=2这个特殊情况,有以下思路:
-
排序后,取数组中间的数。但该方法的时间复杂度为排序算法的时间复杂度O(NlogN)。
-
一次在数组中删掉两个不同的数,不停地删除,直到剩下的数只有一种,一定是那个出现次数大于一半的数。
实现代码:
/** * 特例:找出出现次数大于一半的数 * * @param arr 待查数组 */ public void printHalfMajor (int[] arr) { int cand = 0; //候选 int times = 0; //次数 for (int i = 0; i != arr.length; i++) { if (times == 0) { cand = arr[i]; times = 1; } else if (arr[i] == cand) { times++; } else { times--; } } times = 0; for (int i = 0; i != arr.length; i++) { if (arr[i] == cand) { times++; } } if (times > arr.length / 2) { System.out.println(cand); } else { System.out.println("No such number."); } }
拓展思路二,回到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;
}