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.
public class Solution {
public List<Integer> majorityElement(int[] nums) {
List<Integer> res = new ArrayList<>();
printKMajor(nums, 3, res);
return res;
}
private void printKMajor(int[] nums, int k, List<Integer> res) {
// TODO Auto-generated method stub
if (k < 2) {
return;
}
HashMap<Integer,Integer> cands = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (cands.containsKey(nums[i])) {
cands.put(nums[i], cands.get(nums[i]) + 1);
} else {
if (cands.size() == k - 1) {
allCandsNinusOne(cands);
} else {
cands.put(nums[i], 1);
}
}
}
HashMap<Integer,Integer> reals = getReals(nums, cands);
for (Map.Entry<Integer, Integer> set : reals.entrySet()) {
Integer key = set.getKey();
if (reals.get(key) > nums.length / k) {
res.add(key);
}
}
}
private HashMap<Integer,Integer> getReals(int[] nums, HashMap<Integer, Integer> cands) {
// TODO Auto-generated method stub
HashMap<Integer,Integer> hashMap = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int num = nums[i];
if (cands.containsKey(num)) {
if (hashMap.containsKey(num)) {
hashMap.put(num, hashMap.get(num) + 1);
} else {
hashMap.put(num, 1);
}
}
}
return hashMap;
}
private void allCandsNinusOne(HashMap<Integer, Integer> map) {
// TODO Auto-generated method stub
LinkedList<Integer> linkedList = new LinkedList<>();
for (Map.Entry<Integer, Integer> set : map.entrySet()) {
Integer key = set.getKey();
Integer value = set.getValue();
if (value == 1) {
linkedList.add(key);
}
map.put(key, value - 1);
}
for (Integer integer : linkedList) {
map.remove(integer);
}
}
}