【C++】169. 多数元素

这周写一道算法题。

题目

给定一个大小为 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) 的算法解决此问题。

分析

首先这道题是我朋友发给我的,原题是《剑指Offer》的39题。

这个和数学定义上的众数还不太一样。数学定义上的众数是出现频率最多的数,而且不一定存在;而题目定义的数:

  1. 一定存在
  2. 出现频率大于一半的数

显然的方法是对这个数组进行排序,然后一次遍历即可找出这个数。不过,这样应该达不到线性的时间复杂度。所以,这道题的用了一个叫摩尔投票法的解法。

摩尔投票法

我们后文将这个数称为“众数”,当然,你要知道,这只是一种说法,和真正的众数是不一样的。

摩尔投票法说白了就是一个抵消的过程,假设让所有众数和非众数一一抵消,那最后剩下的一定是这个众数本身。体现在算法里,就是为每个数赋予一个值,众数为+1,非众数为-1,用一个变量votes记录这个值,最后变量为1的一定是众数。

用另一个值num记录遍历到的数,当votes=0时,这意味着我们目前遍历到的数,其中众数和非众数的个数相等,因此数组接下来的部分,依然有众数的votes>非众数的votes,而且后面部分的众数也是整个数组的众数。

总结思路如下:
初始化: 票数统计 votes = 0 , 众数 finalNum.
循环: 遍历数组 nums 中的每个数字 num
当 票数 votes 等于 0 ,则假设当前数字 num 是众数。
num == finalNum 时,票数 votes 自增 1 ;当 num != finalNum 时,票数 votes 自减 1 。
返回值: 返回 finalNum 即可。

代码如下(C++):

int majorityElement(vector<int> &nums)
{
    int finalNum = 0, votes = 0;
    for (int num : nums)
    {
        if (votes == 0)
            finalNum = num;
        votes += (num == finalNum) ? 1 : -1;
    }
    return finalNum;
}

你可能感兴趣的:(c++,算法,leetcode)