法一(摩尔投票)
/**
* 法一(摩尔投票)
* 1. 思路
* (1)每次从序列里选择两个不相同的数字删除掉(或称为“抵消”),最后剩下一个数字或几个相同的数字,就是出现次数大于总数一半的那个
* (2)摩尔投票算法的核心是求多数元素(可以是多于一半,三分之一,四分之一...)
* (3)如果至多选1个代表,那他的票数至少要超过⌊1/2⌋的票数
* (4)如果至多选2个代表,那他们的票数至少要超过⌊1/3⌋的票数
* (5)如果至多选m个代表,那他们的票数至少要超过⌊1/(m+1)⌋的票数
* 2. 复杂度
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*
* @param nums
* @return
*/
public List<Integer> majorityElement(int[] nums) {
List<Integer> ans = new LinkedList<>();
if (nums == null || nums.length == 0) {
return ans;
}
int x = nums[0], cx = 0; // 初始化两个候选人,和他们的计票
int y = nums[0], cy = 0;
for (int num : nums) {
if (x == num) { // 候选人x投票
cx++;
continue;
}
if (y == num) { // 候选人y投票
cy++;
continue;
}
if (cx == 0) { // 更换候选人
x = num;
cx++;
continue;
}
if (cy == 0) { // 更换候选人
y = num;
cy++;
continue;
}
cx--; // 当前元素和两个候选人都不同,则抵消
cy--;
}
cx = 0;
cy = 0;
for (int num : nums) { // 计数
if (x == num) {
cx++;
} else if (y == num) {
cy++;
}
}
if (cx > nums.length / 3) { // 确定候选人x票数是否满足大于len/3
ans.add(x);
}
if (cy > nums.length / 3) { // 确定候选人y票数是否满足大于len/3
ans.add(y);
}
return ans;
}
法二(哈希)
/**
* 法二(哈希)
* 时间复杂度:O(n)
* 空间复杂度:O(n)
*
* @param nums
* @return
*/
public List<Integer> majorityElement_2(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.merge(num, 1, Integer::sum);
}
List<Integer> ans = new LinkedList<>();
int len = nums.length / 3;
map.forEach((key, value) -> {
if (value > len) {
ans.add(key);
}
});
return ans;
}
法三(排序 + 双指针)
/**
* 法三(排序 + 双指针)
* 时间复杂度:O(nlogn)
* 空间复杂度:O(1)
*
* @param nums
* @return
*/
public List<Integer> majorityElement_3(int[] nums) {
Arrays.sort(nums);
List<Integer> ans = new LinkedList<>();
int len = nums.length, left = 0, right = 0;
while (right < len) {
while (right < len && nums[left] == nums[right]) {
right++;
}
if (right - left > len / 3) {
ans.add(nums[left]);
}
left = right;
}
return ans;
}
本地测试
/**
* 229. 多数元素 II
*/
lay.showTitle(229);
Solution229 sol229 = new Solution229();
int[] nums229 = new int[]{3, 2, 3};
System.out.println(Arrays.toString(nums229));
System.out.println(sol229.majorityElement(nums229));
System.out.println(sol229.majorityElement_2(nums229));
System.out.println(sol229.majorityElement_3(nums229));