一、题目
1、审题
2、分析
给出一个整形数组,统计其中元素出现次数超过数组长度 1/3 的元素。
二、解答
1、思路
方法一、
采用一个 Map 统计元素出现的次数。
1 public List<Integer> majorityElement(int[] nums) { 2 3 int len; 4 List<Integer> list = new ArrayList<Integer>(); 5 if(nums == null || (len = nums.length) == 0) 6 return list; 7 int time = len / 3 + 1; 8 HashMap<Integer, Integer> map = new HashMap<>(); 9 10 for(int i: nums) { 11 if(map.containsKey(i)) 12 map.put(i, map.get(i) + 1); 13 else 14 map.put(i, 1); 15 } 16 for(Entry<Integer, Integer> entry: map.entrySet()) { 17 if(entry.getValue() >= time) 18 list.add(entry.getKey()); 19 } 20 return list; 21 }
方法二、
Boyer-Moore majority vote algorithm(摩尔投票算法)
这是一种在线性时间O(n)和空间复杂度的情况下,在一个元素序列中查找包含最多的元素(超过1/2才检测的到)。
要求出现次数超过 1/3 的元素,则这样的元素最多存在 2 个,可以采用 摩尔投票法统计出出现次数最多的两个元素,最终在判断是否这两个元素符合出现次数超过 1/3。
1 public List<Integer> majorityElement2(int[] nums) { 2 int len; 3 List<Integer> list = new ArrayList<Integer>(); 4 if(nums == null || (len = nums.length) == 0) 5 return list; 6 int time = len / 3 + 1; 7 int count1 = 0, count2 = 0, candidate1 = -1, candidate2 = -1; 8 for(int num: nums) { 9 if(num == candidate1) 10 count1++; 11 else if(num == candidate2) 12 count2++; 13 else if(count1 == 0){ 14 candidate1 = num; 15 count1 = 1; 16 } 17 else if(count2 == 0) { 18 candidate2 = num; 19 count2 = 1; 20 } 21 else { 22 count1--; 23 count2--; 24 } 25 } 26 count1 = 0; 27 count2 = 0; 28 for(int num: nums) { 29 if(num == candidate1) 30 count1++; 31 else if(num == candidate2) 32 count2++; 33 } 34 if(count1 >= time) list.add(candidate1); 35 if(count2 >= time) list.add(candidate2); 36 37 return list; 38 }