Idiot-maker

  :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

https://leetcode.com/problems/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.

Hint:

  1. How many majority elements could it possibly have?
  2. Do you have a better hint? Suggest it!

解题思路:

这题是 Majority Element 的follow-up,但是不同的是,上题要求的是出现次数大于floor(n/2)的数字,这一题是要求出所有大于floor(n/3)。问题是,这样的数字可能有几个?

上一题很显然的,只要求出有且仅有的一个数字,而这一题,我们只要定心想一下,这样的数字最多只可能有两个。

还是用Boyer-Moore Majority Vote Algorithm的方法,很容易想到count和candidate的记数,各用两个变量去记录。

大体思路类似,问题是,当当前数字和candidate1、candidate2都不相等的时候,怎么办?

这里我们首先去抵消掉出现次数较小的那个。为什么?因为如果是较大的,那么count2就永远是1了。

另外,如果count1和count2都不为0的时候,count1和count2都要减一。这个非常重要,也比较容易理解。

public class Solution {
    public List<Integer> majorityElement(int[] nums) {
        List<Integer> res = new ArrayList<Integer>();
        if(nums.length == 0) {
            return res;
        }
        if(nums.length == 1) {
            res.add(nums[0]);
            return res;
        }
        int count1 = 0, count2 = 0;
        int candidate1 = nums[0], candidate2 = nums[1];
        for(int num : nums) {
            if(num == candidate1) {
                count1++;
            } else if(num == candidate2) {
                count2++;
            } else {
                if(count1 < count2) {//总是首先操作数量较少的数字
                    if(count1 == 0) {
                        candidate1 = num;
                        count1 = 1;
                    } else {
                        count1--;
                        count2--;
                    }
                } else {
                    if(count2 == 0) {
                        candidate2 = num;
                        count2 = 1;
                    } else {
                        count1--;
                        count2--;
                    }
                }
            }
        }
        count1 = 0;
        count2 = 0;
        for(int num : nums) {
            if(num == candidate1) {
                count1++;
            } else if(num == candidate2) {
                count2++;
            }
        }
        if(count1 > nums.length / 3) {
            res.add(candidate1);
        }
        if(count2 > nums.length / 3) {
            res.add(candidate2);
        }
        return res;
    }
}

后来在discuss里发现人家的解法和我的差不多,但是可以完全不用管count1和count2的大小,只要count1和count2里有一个==0,就去更新它就可以了。

代码如下

public class Solution {
    public List<Integer> majorityElement(int[] nums) {
        List<Integer> res = new ArrayList<Integer>();
        if(nums.length == 0) {
            return res;
        }
        if(nums.length == 1) {
            res.add(nums[0]);
            return res;
        }
        int count1 = 0, count2 = 0;
        int candidate1 = nums[0], candidate2 = nums[1];
        for(int num : nums) {
            if(num == candidate1) {
                count1++;
            } else if(num == candidate2) {
                count2++;
            } else {
                if(count1 == 0) {
                    candidate1 = num;
                    count1 = 1;
                } else if(count2 == 0) {
                    candidate2 = num;
                    count2 = 1;
                } else {
                    count1--;
                    count2--;
                }
            }
        }
        count1 = 0;
        count2 = 0;
        for(int num : nums) {
            if(num == candidate1) {
                count1++;
            } else if(num == candidate2) {
                count2++;
            }
        }
        if(count1 > nums.length / 3) {
            res.add(candidate1);
        }
        if(count2 > nums.length / 3) {
            res.add(candidate2);
        }
        return res;
    }
}

这道题是蛮好的一个follow-up,借鉴了上一题的基本思路,由需要对题目有更深层次的理解。

posted on 2015-07-01 20:42  NickyYe  阅读(292)  评论(0编辑  收藏  举报