Leetcode 0229: Majority Element II

题目描述:

Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times.
Follow-up: Could you solve the problem in linear time and in O(1) space?

Example 1:

Input: nums = [3,2,3]
Output: [3]

Example 2:

Input: nums = [1]
Output: [1]

Example 3:

Input: nums = [1,2]
Output: [1,2]

Constraints:

1 <= nums.length <= 5 * 104
-109 <= nums[i] <= 109

Time complexity: O(n)
Space complexity: O(1)
摩尔投票法Boyer-Moore Voting Algorithm:
一般情况一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/k ⌋ 次的元素。
则n/k的众数最多只有k - 1个。假设有k个众数,则 出现次数(⌊ n/k ⌋ +1) × \times × 众数个数 k > n. 以此题为例 k = 3, 把此情景想像成在大会中投票选出两个候选者, 则有两个候选 n1 和n2。

  1. 如果投n1(当前元素等于n1),则n1的票数 c1++;
  2. 如果投n2(当前元素等于n2),则n2的票数c2++;
  3. 如果n1,n2都不投(即当前值与n1,n2都不相等),那么检查此时n1或n2的票数是否为0:
    3.1 如果为0,则当前元素成为新的候选人替代掉票数为0的人;
    3.2 如果n1,n2两个人的票数都不为0,那么n1,n2两个候选人的票数均减一;
    最后会有这么几种可能:有2个大于n/3,有1个大于n/3,有0个大于n/3,遍历结束后选出了两个候选人,但是这两个候选人是否满足> n/3,还需要再遍历一遍数组,找出两个候选人的具体票数,因为题目没有像169题保证一定有。

相似题:leetcode:169

class Solution {
    public List<Integer> majorityElement(int[] nums) {
        List<Integer> res = new ArrayList<>();
        int c1 = 0;
        Integer n1 = nums[0];
        int c2 = 0;
        Integer n2 = nums[0];
        for (int n: nums) {
            if(n1 != null && n1 == n){
                c1++;
            }else if(n2 != null && n2 == n){
                c2++;
            }else if(c1 == 0){
                c1++;
                n1 = n;
            }else if(c2 == 0){
                c2++;
                n2 = n;
            }else{
                c1--;
                c2--;
            }
        }
        
        c1 = 0;
        c2 = 0;
        for (int n: nums) {
            if(n == n1){
                c1++;
            }else if(n == n2){
                c2++;
            }
        }
        int n = nums.length;
        if(c1 > n/3){
            res.add(n1);
        }
        if(c2 > n/3){
            res.add(n2);
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值