8.7在数组中找出出现次数大于N÷K的数

版权声明:本文采用 知识共享署名4.0 国际许可协议进行许可。 https://blog.csdn.net/youmian6868/article/details/85200059
题目

给定一个整形数组arr,再给定一个整数K,打印所有出现次数大于N/K的数,如果没有这样的数,打印提示信息。


首先分析K=2这个特殊情况,有以下思路:

  1. 排序后,取数组中间的数。但该方法的时间复杂度为排序算法的时间复杂度O(NlogN)。

  2. 一次在数组中删掉两个不同的数,不停地删除,直到剩下的数只有一种,一定是那个出现次数大于一半的数。

    实现代码:

    /**
     * 特例:找出出现次数大于一半的数
     *
     * @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;
}

猜你喜欢

转载自blog.csdn.net/youmian6868/article/details/85200059