Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.
You may assume that the array is non-empty and the majority element always exist in the array.
题解
题目要求就是找到出现次数超过一半的数,即大于n/2。
解法一:排序 —— 时间复杂度O(nlogn) 空间复杂度O(1)
一个数字在数组中的出现次数超过了一半,那么在已排好序的数组索引的N/2处(从零开始编号),就一定是这个数字。
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(), nums.end());
return nums[nums.size() / 2];
}
};
解法二:Hash表 —— 时间复杂度O(n) 空间复杂度O(n)
既要缩小总的时间复杂度,那么可以用查找时间复杂度为O(1)的hash表,即以空间换时间。哈希表的键值(Key)为数组中的数字,值(Value)为该数字对应的次数。
遍历时当一个数字出现的次数大于n/2,输出即可。
class Solution {
public:
int majorityElement(vector<int>& nums) {
unordered_map<int, int> counts;
int n = nums.size();
for (int i = 0; i < n; i++)
if (++counts[nums[i]] > n / 2)
return nums[i];
}
};
解法三:随机 —— 时间复杂度O(n*x) 空间复杂度O(1)
这里x指的是取随机数的次数,你可能会觉得很扯,但是这个算法的效率绝对不差。
我们可以想一想,每次直接找到结果的概率是 (出现次数最多的数的次数)/ n > 1/2。
所以如果我们认为(1/2)^k为0,当k为任意大于常数x的整数,则最多x次得到结果,时间复杂度就相当于O(n)。
class Solution {
public:
int majorityElement(vector<int>& nums) {
int n = nums.size();
srand(unsigned(time(NULL)));
while (true) {
int idx = rand() % n;
int candidate = nums[idx];
int counts = 0;
for (int i = 0; i < n; i++)
if (nums[i] == candidate)
counts++;
if (counts > n / 2) return candidate;
}
}
};
解法四:位运算 —— 时间复杂度O(n) 空间复杂度O(1)
找出每一位上1出现次数超过一半的,合在一起就是结果。因为如果major该位为0,其他所有的数该位都为1,也不会超过一半。
class Solution {
public:
int majorityElement(vector<int>& nums) {
int major = 0, n = nums.size();
for (int i = 0, mask = 1; i < 32; i++, mask <<= 1) {
int bitCounts = 0;
for (int j = 0; j < n; j++) {
if (nums[j] & mask) bitCounts++;
if (bitCounts > n / 2) {
major |= mask;
break;
}
}
}
return major;
}
};
解法五:个人推荐 —— 时间复杂度O(n) 空间复杂度O(1)
利用性质——出现超过一半次数,若每次碰见他加1,不是他-1,最后结果大于0。
一次遍历数组,保存两个值,一个major,用来保存数组中遍历到的某个数字,一个count,表示当前数字的出现次数。当count为0时,将major更新为当前数,count初始化为1,否则判断当前数是否与major相等,相等count+1,不等-1。
可能有人会有疑问,可以确保最后major就是主要数吗,答案是肯定的。
首先易知major肯定会被赋为主要数,假设我们在位置k时major被赋为主要数,则在k之前major最多出现了k/2次(否则在k之前就被赋为major了),则在剩下的n-k中major的次数必然大于(n-k)/2。
所以可以确保结果正确。
class Solution {
public:
int majorityElement(vector<int>& nums) {
int major, count = 0;
for(int i = 0; i < nums.size(); i++){
if(count == 0){
major = nums[i];
count = 1;
}
else count += (nums[i] == major) ? 1 : -1;
}
return major;
}
};