题干:

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

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

示例 1:

输入:nums = [3,2,3] 输出:3 示例 2:

输入:nums = [2,2,1,1,1,2,2] 输出:2  

提示: n == nums.length 1 n 5 * 104 -109 nums[i] 109  

进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。

链接:https://leetcode.cn/problems/majority-element

解题思路:

读完题干后,脑子里第一反应是用一个HashMap来记录每个元素的出现次数,然后再取出出现次数最多的那个数字。但是仔细一想绝对不是最完美的方案,且不说题干中的进阶里说明了用空间复杂度为常数的算法来解题,这个题目本身给的条件也是多了的,因为多数元素的定义是要超过长度的一半,而非只是数量最多。

初中生的一个常识就是如果老师给你的条件多了,那么这个题目基本都是会利用到这个条件的,而放在算法中就是我们去寻求时间复杂度与空间复杂度优化的突破口。

既然元素长度超出了一半,那么一个很简单的演绎过程就是我这个多数元素比其它任何元素都要多,那简单遍历一下,用这个多数元素与其它元素玩“消消乐”,那么最终剩下的肯定是这个多数元素。

这在算法中叫摩尔投票法,具体的实现过程:

/**
 * @param {number[]} nums
 * @return {number}
 */
var majorityElement = function(nums) {
    var voteElement = nums[0];
    var voteNum = 1;
    for (let i = 1; i < nums.length; i++) {
        if (nums[i] === voteElement) {
            voteNum += 1;
        } else {
            voteNum -=1;
            if (voteNum === 0) {
                voteElement = nums[i + 1];
            }
        }
    }
    return voteElement;
};