# 数组中出现次数超过数组长度一半的数字

# 一、题目描述

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

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

示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2   限制: 1 <= 数组长度 <= 50000

# 二、解题思路

  1. 哈希表统计法: 遍历数组 nums ,用 HashMap 统计各数字的数量,即可找出 众数 。此方法时间和空间复杂度均为 O(N)。
/**
 * @param {number[]} nums
 * @return {number}
 */
var majorityElement = function(nums) {
    if (nums.length === 0) return -1;
    if (nums.length === 1) return nums[0];

    let map = new Map(); // {值:次数}
    for (let i = 0; i < nums.length; i++) {
        let value = nums[i];
        if (map.has(value)) {
            let count = map.get(value);
            if ((count + 1) * 2 > nums.length) return value;
            map.set(value, count+1);
        } else {
            map.set(value, 1);
        }
    }

    return -1;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  1. 数组排序法: 将数组 nums 排序,数组中点的元素 一定为众数。
/**
 * @param {number[]} nums
 * @return {number}
 */
var majorityElement = function(nums) {
    if (nums.length === 0) return -1;
    if (nums.length === 1) return nums[0];

    nums.sort((a,b) => a - b);

    return nums[parseInt(nums.length / 2)];
};
1
2
3
4
5
6
7
8
9
10
11
12
  1. 摩尔投票法:核心理念为 票数正负抵消 。此方法时间和空间复杂度分别为 O(N) 和 O(1) ,为本题的最佳解法。
/**
 * @param {number[]} nums
 * @return {number}
 */
var majorityElement = function(nums) {
    if (nums.length === 0) return -1;
    if (nums.length === 1) return nums[0];

    let votes = 0;
    let x = 0;
    for (let i = 0; i < nums.length; i++) {
        if (votes === 0) x = nums[i]; 
        votes += x === nums[i] ? 1 : -1;
    }
    return x;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
上次更新: 1/5/2022, 9:25:14 AM