【刷题第16天】数组中出现次数超过一半的数字

65 阅读2分钟

“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2

二、思路分析:

哈希表法

最简单的方法应该就是利用哈希表了,我们定义一个 hash(javascript 中应该是 map),键值对分别存储数字和数字出现次数,同时可以维护一个出现频数的最大值(可以省去遍历完毕后再遍历hash获取最大频次的时间),最后我们可以直接判断频次最大值/数组长度得比值是否大于 1/2 即可

摩尔法

博耶-摩尔多数投票算法( Boyer–Moore majority vote algorithm ),中文常作多数投票算法、摩尔投票算法等,是一种用来寻找一组元素中占多数元素的常数空间级时间复杂度算法。

摩尔投票法核心在于投票与计数两个阶段。 例如我们举下面的案例: 1 2 2 2 3 来理解一下摩尔投票法。

  • 投票阶段:
    • 首先我们选取第一个元素为候选人,维护一个count 初始值为 0
    • 遍历数组,当元素与候选人不同是, count --,若相同 count ++
    • 当 count 为 0 时,更换候选人
  • 计数阶段:
    • 投票结束后,如果 count 非 0,则证明此候选人有概率占据总数得一半之上
    • 例如 [1,2,2,1,3,3] 这种,前面两个候选人选票互相内耗了,第三个候选人也没有达到总票数的一半,因此我们需要进行计数

三、AC 代码:

var majorityElement = function(nums) {
    let cand = nums[0];
    let count = 0;
    nums.forEach(val => {
        // 如果count = 0,那么则替换候选人
        if(!count) {
            cand = val;
        }
        // 如果当前值等于候选人,count ++;否则 count --
        if(cand === val) {
            count++;
        } else {
            count--;
        }
    }
    return nowCandidate;
};

四、总结:

摩尔投票法还是挺有意思得一种方法,我在查阅资料是发现此种方法还能用于同时投出两个候选人或者多个候选人,有机会去做一下该题目。