主元素问题
问题描述
主元素的定义为:数组中出现次数超过数组长度一半以上的元素。
输入一个无序数组,输出主元素(不能保证一定存在主元素)。
解决思路
经典的芯片测试问题:
1. 首先将数组的首元素置为主元素候选,并附加一个计数器,初始为1;
2. 遍历数组之后的元素,如果元素与候选元素相等,计数器加1;否则计数器减1;途中如果计数器为0,则将当前遍历元素设为候选元素。
因为不能保证最后得到的候选元素一定是主元素,例如[1, 2, 3]。
所以最后要对该候选元素进行验证,验证方式为重新遍历一遍数组,对该候选元素进行计数,最后判断该次数是否超过数组长度的一半。
程序
public class MajorityElem { public int getMajorityElem(int[] nums) { if (nums == null || nums.length == 0) { return 0; } int candidate = nums[0]; int count = 1; for (int i = 1; i < nums.length; i++) { if (count == 0 || candidate == nums[i]) { candidate = nums[i]; ++count; } else { --count; } } if (verify(nums, candidate)) { return candidate; } return -1; } private boolean verify(int[] nums, int candidate) { int count = 0; for (int n : nums) { if (n == candidate) { ++count; } } return count > nums.length / 2; } }
Follow Up
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.
解决思路
思路与主元素问题相似,不同的在于需要设置两个candidates(数组中满足如上定义的元素个数最多为2个)。
程序
public class MajorityElem2 { public List<Integer> majorityElement(int[] nums) { List<Integer> res = new ArrayList<Integer>(); if (nums == null || nums.length == 0) { return res; } int candicate1 = 0, candicate2 = 0; int count1 = 0, count2 = 0; for (int i = 0; i < nums.length; i++) { if (count1 == 0 || candicate1 == nums[i]) { ++count1; candicate1 = nums[i]; } else if (count2 == 0 || candicate2 == nums[i]) { ++count2; candicate2 = nums[i]; } else { --count1; --count2; } } verify(nums, candicate1, candicate2, res); return res; } private void verify(int[] nums, int candicate1, int candicate2, List<Integer> res) { int len = nums.length; int count1 = 0, count2 = 0; for (int n : nums) { if (n == candicate1) { ++count1; } if (n == candicate2) { ++count2; } } if (count1 > len / 3) { res.add(candicate1); } if (candicate1 == candicate2) { return ; } if (count2 > len / 3) { res.add(candicate2); } } }
Bugs:
Case:[0, 0, 0], output: 0, 0
candidate1和candidate2有可能相同,如果都满足,只需要输出一个即可。
leetcode题目链接
https://leetcode.com/problems/majority-element/
https://leetcode.com/problems/majority-element-ii/