Leetcode 229 Majority Element II

Leetcode 229 Majority Element II

题目

Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times.

Note: The algorithm should run in linear time and in O(1) space.

Example 1:
Input: [3,2,3]
Output: [3]

Example 2:
Input: [1,1,1,3,3,2,2,2]
Output: [1,2]

思路

自己只想到使用HashMap记录次数,代码如下。

class Solution {
    public List<Integer> majorityElement(int[] nums) {
        List<Integer> res = new LinkedList<>();
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
            if (map.get(num) > nums.length / 3 && !res.contains(num)) res.add(num);
            if (res.size() == 2) return res;
        }
        return res;
    }
}

但是题目提示使用O(1)空间。使用Boyer-Moore Majority Vote Algorithm,思路如下。
根据题目要求最多只可能有两个结果,记录为cand1,cand2,初始化为数组中两个不同的值。该算法的核心是删除两个不同的数不影响majority number,分以下几种情况:
1.删除的两个都是majority number
因为有 a > n u m s . l e n g t h / 3 a > nums.length / 3 a>nums.length/3我们可以得到 a − 1 > ( n u m s . l e n g t h − 3 ) / 3 a - 1 > (nums.length - 3) / 3 a1>(nums.length3)/3,减3是因为去掉了两个数和引发该情况的数(一个遍历的时候和这两个majority number不同的数)
e.g. [ 1 , 2 , 3 , 2 , 1 ] [1,2,3,2,1] [1,2,3,2,1] 这个例子在3的时候进入代码将1和2的计数减去1,但是1和2还是 [ 2 , 1 ] [2,1] [2,1]的majority number

2.删除的两个都不是majority number,显然无影响

3.删除的一个是一个不是,就是一二情况的结合
e.g. [ 2 , 1 , 4 , 5 , 2 ] [2,1,4,5,2] [2,1,4,5,2] 这个例子在4的时候将2和1的计数减去1,此时2仍是 [ 5 , 2 ] [5,2] [5,2]的majority element,虽然在5的时候cand1从2换成了5,但是最后的结果中cand仍然包含2(cand2=2)

从上面的例子也可以看出,在算法的结尾,只能保证majority element在cand中但是cand并不一定全是,所以还要重新遍历返回答案。

参考Leetcode给出的sample代码如下:

class Solution {
    public List<Integer> majorityElement(int[] nums) {
        List<Integer> result = new ArrayList<>();
        if(nums == null || nums.length == 0)
            return result;
        
        int cand1 = 0, cand2 = 0;
        
        int count1 = 0, count2 = 0;
        
        for(int num : nums){
            if(num == cand1){
                count1 ++;
                continue;
            }
            
            if(num == cand2){
                count2 ++;
                continue;
            }
            
            if(count1 == 0){
                cand1 = num;
                count1 = 1;
                continue;
            }
            
            if(count2 == 0){
                cand2 = num;
                count2 = 1;
                continue;
            }
            
            count1 --;
            count2 --;
            
        }
        
        count1 = 0;
        count2 = 0;
        
        for(int num : nums){
            if(num == cand1){
                count1 ++;
            }else if(num == cand2){
                count2 ++;
            }
        }
        
        if(count1 > nums.length / 3)
            result.add(cand1);
        
        if(count2 > nums.length / 3)
            result.add(cand2);
        
        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值