leetcode——Majority Element II

题目:

Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in linear time and in O(1) space.

分析:

        针对“选择出现次数大于n/2的元素”的问题,每次舍弃两个不同的元素,最后剩下的元素有可能就是超过半数的那个。那么这道题同样可以采用这样的思路,每次舍弃三个互不相同的元素,那么剩下的元素有可能是出现次数超过n/3的那个。

1、这个思路类似于将n个元素分组,依次选择三个互不相同的元素组成一组(如果存在的话),那么可以分成(n+1)/3组,最后一组的元素个数可能小于3个,显然,出现次数超过n/3的元素肯定出现在最后一组中(抽屉原理)。

2、最后一组中的元素不一定都出现超过n/3次。

3、出现次数超过n/3的元素最多两个

代码维护两个不相等的候选值(可能出现次数超过n/3次)和与它们对应的计数器,考察每个新元素,这个新元素有可能被选为候选值也有可能作为“三个互不相等的元素”被舍弃

1、两个候选值都存在

        比较两个候选值与新元素,三者都不相等,那么舍弃这三个元素(计数器减一);

        如果新元素与其中一个候选值相等,那么增加对应的计数器

2、两个候选值不都存在(计数器为0)

        如果新元素和某个存在的候选值相等,那么增加对应的候选值;

        如果没有与新元素相等的候选值,那么将新元素选为候选值;

        如果两个候选值都不存在,那么直接更新候选值。

class Solution {
private:
    bool check(vector<int>& nums, int val) 
    {
        int count = 0;
        for (int i = 0; i < nums.size(); ++i) 
        {
            if (val == nums[i]) ++count;
        }
        return count > nums.size() / 3;
    }
public:
    vector<int> majorityElement(vector<int>& nums) {
        //每次删除三个不相同的元素,最后剩下的数字就是结果
        vector<int> res;
        if (nums.empty()) 
        {
            return res;
        }
        int num1, num2, count1 = 0, count2 = 0;
        for (int i = 0; i < nums.size(); ++i) 
        {
            if (count1 == 0 || count2 == 0) 
            {
                if (count1 == 0 && count2 == 0) 
                {
                    num1 = nums[i];
                    ++count1;
                }
                else if (count1 == 0) //count2肯定不是0
                {
                    if (num2 == nums[i]) 
                    {
                        ++count2;
                    }
                    else 
                    {
                        num1 = nums[i];
                        ++count1;
                    }
                }
                else //count1 != 0
                {
                    if (num1 == nums[i]) 
                    {
                        ++count1;
                    }
                    else 
                    {
                        num2 = nums[i];
                        ++count2;
                    }
                }
            }
            else if (nums[i] != num1 && nums[i] != num2) 
            {
                //删除三个不同的元素
                --count1;
                --count2;
            }
            else if (nums[i] == num1)
            {
                ++count1;
            }
            else 
            {
                ++count2;
            }
        }
        if (count1 != 0 && check(nums, num1)) res.push_back(num1);
        if (count2 != 0 && check(nums, num2)) res.push_back(num2);
        return res;
    }
};
因为候选值不一定就是出现次数大于n/3的元素,因此需要check()。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值