剑指 Offer 39. 数组中出现次数超过一半的数字

alt

HashMap遍历

class Solution {
    public int majorityElement(int[] nums) {
        int n = nums.length;
        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
            if (map.get(num) > n / 2) 
                return num;
        }
        return 0;
    }
}

排序后的数组中点的数字一定为众数,nlogn排序。

摩尔投票

  • 摩尔投票法:核心理念为票数正负抵消。时间复杂度为O(n),空间复杂度为O(1)。

1.假如a是众数,删掉一个a和一个其他数,a仍然是众数

2.假如a是众数,b不是众数,删掉k个b,删掉k个其他数,a仍然是众数,因为删掉的a最多也就是k个 那删掉k个a和k个其他数,a仍然是众数

所以进行摩尔投票法,选取第一个数b,从前往后计数,若出现这个数则count+1,出现其他数则count-1,然后当count=0时,前面恰好出现了k个b和k个非b,根据上面的原理,我们把这段数组删掉,众数仍然不变

然后对后面的数组反复执行操作就ok了,直到删到b遍历到结尾count也没有归零,证明后面b的数量大于一半,b是众数.

class Solution {
    public int majorityElement(int[] nums) {
        int x = 0, vote = 0;
        for (int num : nums) {
            if (vote == 0) x = num;
            vote += num == x ? 1 : -1;
        }
        return x;
    }
}