229求众数 II(摩尔投票法)

1、题目描述

给定一个大小为 n 的数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。

说明: 要求算法的时间复杂度为 O(n),空间复杂度为 O(1)。

2、示例

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

3、题解

基本思想:摩尔投票法,n/k的众数最多只有k-1个,设定两个候选人candidate1和candidate2,票数分别是cnt1和cnt2

  • 1、如果投A(当前元素等于A),则A的票数++;
  • 2、如果投B(当前元素等于B),B的票数++;
  • 3、如果A, B都不投(即当前与A,B都不相等), 那么检查此时A或B的票数是否减为0,如果为0, 则当前元素成为新的候选人;如果A, B两个人的票数都不为0,那么A, B两个候选人的票数均减一。
  • 最后会有这么几种可能:有2个大于n/3,有1个大于n/3,有0个大于n/3
  • 遍历结束后选出了两个候选人,但是这两个候选人是否满足>n/3,还需要再遍历一遍数组,找出两个候选人的具体票数,因为题目没有像169题保证一定有。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
class Solution {
public:
	vector<int> majorityElement(vector<int>& nums) {
		//基本思想:摩尔投票法,n/k的众数最多只有k-1个
		//设定两个候选人candidate1和candidate2,票数分别是cnt1和cnt2
		//1、如果投A(当前元素等于A),则A的票数++;
		//2、如果投B(当前元素等于B),B的票数++;
		//3、如果A, B都不投(即当前与A,B都不相等), 那么检查此时A或B的票数是否减为0,如果为0, 则当前元素成为新的候选人;如果A, B两个人的票数都不为0,那么A, B两个候选人的票数均减一。
		//最后会有这么几种可能:有2个大于n/3,有1个大于n/3,有0个大于n/3
		//遍历结束后选出了两个候选人,但是这两个候选人是否满足>n/3,还需要再遍历一遍数组,找出两个候选人的具体票数,因为题目没有像169题保证一定有。
		vector<int> res;
		int candidate1 = 0, candidate2 = 0;
		int cnt1 = 0, cnt2 = 0;
		for (auto num:nums)
		{
			if (nums == candidate1)
				cnt1++;
			else if (nums == candidate2)
				cnt2++;
			else
			{
				if (cnt1 == 0)
				{
					candidate1 = nums;
					cnt1 = 1;
				}
				else if (cnt2 == 0)
				{
					candidate2 = nums;
					cnt2 = 1;
				}
				else
				{
					cnt1--;
					cnt2--;
				}
			}
		}
		cnt1 = 0;
		cnt2 = 0;
		for (auto num : nums)
		{
			if (num == candidate1)
				cnt1++;
			else if (num == candidate2)
				cnt2++;
		}
		if (cnt1 > nums.size()/3)
			res.push_back(candidate1);
		if (cnt2 > nums.size()/3)
			res.push_back(candidate2);
		return res;
	}
};
int main()
{
	Solution solute;
	vector<int> nums = { 1,1,1,3,3,2,2,2 };
	vector<int> res = solute.majorityElement(nums);
	for_each(res.begin(), res.end(), [](const auto v) {cout << v << endl; });
	return 0;
}

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值