题目:剑指 Offer 39. 数组中出现次数超过一半的数字
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
注意:本题将这个出现次数超过数组长度一半的数字称为——众数,这与数学中众数的定义不同。
示例1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
法一:摩尔投票法
class Solution39_01 {
public int majorityElement(int[] nums) {
int x = 0, votes = 0, count = 0;
for (int num : nums) {
if (votes == 0) x = num;
votes += num == x ? 1 : -1;
}
// 验证 x 是否为众数
for (int num : nums)
if (num == x) count++;
return count > nums.length / 2 ? x : 0; // 当无众数时返回 0
}
}
时间复杂度:O(n)
空间复杂度:O(1)
法二:先排序
class Solution39_02 {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}
}
时间复杂度:取决于排序算法
空间复杂度:取决于排序算法
法三:使用Map
class Solution39_03 {
public int majorityElement(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
int count = map.getOrDefault(num, 0) + 1;
if (count > nums.length / 2)
return num;
map.put(num, count);
}
return -1;
}
}
时间复杂度:O(n)
空间复杂度:O(n)
法四:位运算
class Solution39_04 {
public int majorityElement(int[] nums) {
int major = 0;
int length = nums.length;
for (int i = 0, mask = 0; i < length; i++, mask<<=1){
int bitCounts = 0;
for(int j=0;j<length; j++){
if((nums[j] & mask) != 0)
bitCounts++;
if(bitCounts > length/2){
major |= mask;
break;
}
}
}
return major;
}
}