LeetCode 刷题 [C++] 第169题. 多数元素 (排序法、哈希表、摩尔投票法)

博客围绕在数组中查找多数元素(出现次数大于 ⌊ n/2 ⌋)的问题,介绍了三种算法。排序法将数组排序后取中间位置元素;哈希表法用哈希表记录元素出现次数,动态判断是否超过一半;摩尔投票法通过计数比较找出多数元素,并分析了各算法复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:
输入: [3,2,3]
输出: 3

示例 2:
输入: [2,2,1,1,1,2,2]
输出: 2

题意解析:给一个数组,其中有一个数出现的次数大于数组长度的一半,找出并返回该数。

一、排序法

由题意分析可知:
众数出现的个数超过了数组长度的一半,如果将数组进行排序,那么这个众数一定占据了中间位置,也就是下标为n/2的位置一定被该众数占据
这个思路通过画图可直观的看出来。
在此就直接上代码:

lass Solution {
public:
    int majorityElement(vector<int>& nums) {
        int len = nums.size();
        sort(nums.begin(),nums.end());
        return nums[len>>1];
    }
};

复杂度分析
时间复杂度:O(nlogn)。将数组排序的时间复杂度为 O(nlog⁡n)。
空间复杂度:O(log⁡n)。使用语言自带的排序算法,需要使用 O(log⁡n)的栈空间。

AC结果
在这里插入图片描述

二、哈希表法

题意是查找出现次数超过数组长度一半的数,因此,我们可以将已经遍历的数组的数放入一个哈希表中,元素作为哈希表的key,数字出现的次数作为value,因为哈希表的查找的时间复杂度为O(1)。即用空间换取时间。
在动态更新数组中数字出现的次数时,判断当前遍历数字出现的个数是否超过数组长度的一半,如果超过,则直接返回该数。
具体代码实现

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int len = nums.size();
        unordered_map<int,int> tmp;
        for(auto& n:nums) {
            ++tmp[n];
            if(tmp[n] > len>>1)
                return n;
        }
        return nums[0];
    }
};

复杂度分析
时间复杂度:O(n),其中 n 是数组 nums 的长度。
空间复杂度:O(n)。哈希表最多包含 n−(n/2)个键值对,所以占用的空间为 O(n)。

AC结果
在这里插入图片描述

三、摩尔投票法

再次回顾下题目:寻找数组中超过一半的数字,即该数字出现的次数比数组中其它数字出现次数的总和都大
也就是说,如果将数组中要查找的众数替换成1,其它数字替换成-1,若让其相加,最后的值肯定大于0。
因此,可以执行以下操作解析题目:
1.设置两个变量res和cnt,res用来保存数组中遍历到的某个数字,cnt表示res当前出现的次数,一开始res保存为数组中的第一个数字,cnt为1.
2.遍历整个数组:

  • 如果数字与res保存的数字相同,则++cnt;
  • 如果数字与res保存的数字不同,则–cnt;
  • 如果出现次数cnt变为0,res进行变化,保存为当前遍历的那个数字,同时把cnt重置为1.

3.遍历完数组中的所有元素即可返回res的值。

具体代码实现

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int res=nums[0],cnt=1,len=nums.size();
        for(int i=1;i<len;++i) {
            if(nums[i] == res) ++cnt;
            else --cnt;
            if(!cnt) {
                res=nums[i];
                cnt=1;
            }
        }
        return res;
    }
};

复杂度分析
时间复杂度:由于只需要遍历一次,因此时间复杂度为O(n)。
空间复杂度:因为只需要常数级别的额外空间,所以空间复杂度为O(1)。

AC结果
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值