Majority Element II

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,借鉴了上一题的基本思路,由需要对题目有更深层次的理解。

你可能感兴趣的:(element)