/**
* Index: 169
* Title: Majority Element
* Author: ltree98
**/
题意
给定一个数组,求数组内出现最频繁的数字。
- 最频繁的元素出现次数将大于一半数组长度
我的
思路
时间复杂度:O(nlogn)
空间复杂度:O(1)
std::sort会根据数据量改变算法,达到平均时间复杂度为 O(nlogn)
最重要一点在于,题目中注释,最频繁的元素出现次数会大于一半数组长度。
所以,在排序后,最频繁数字一定会在数组中间。
实现
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(), nums.end());
return nums[int(nums.size()/2)];
}
};
进阶
这个题虽然简单,但是八仙过海,各显神通,有很多有意思且很巧妙的方法。
随机
这个方法,很简单,就是随机一个index,然后遍历数组,看这个index的数在数组内出现次数,是否大于n/2;若错误,继续随机index;直到出现符合规则数字为止。
class Solution {
public:
int majorityElement(vector<int>& nums) {
int len = nums.size();
srand(unsigned(time(NULL)));
while (true) {
int index = rand() % len;
int aim = nums[index];
int counts = 0;
for (int i = 0; i < len; i++)
if (nums[i] == aim)
counts++;
if (counts > len / 2)
return aim;
}
}
};
分治
分而治之,递归找各部分最频繁的元素。
class Solution {
public:
int majorityElement(vector<int>& nums) {
return majority(nums, 0, nums.size() - 1);
}
private:
int majority(vector<int>& nums, int left, int right) {
if(left == right)
return nums[left];
int mid = left + (right - left) / 2;
int leftMid = majority(nums, left, mid);
int rightMid = majority(nums, mid + 1, right);
if(leftMid == rightMid)
return leftMid;
int leftMidCount = count(nums.begin() + left, nums.begin() + right + 1, leftMid);
int rightMidCount = count(nums.begin() + left, nums.begin() + right + 1, rightMid);
if(leftMidCount > rightMidCount)
return leftMid;
else
return rightMid;
}
};
摩尔投票
大概原理就是,最频繁的元素是一队,其他元素是一队,两队互相出一个元素抵消,直到最后剩下的为胜者,由于最频繁元素大于n/2,所以最后剩下的就是最频繁的元素。
class Solution {
public:
int majorityElement(vector<int>& nums) {
int major, counts = 0, n = nums.size();
for (int i = 0; i < n; i++) {
if (!counts) {
major = nums[i];
counts = 1;
}
else counts += (nums[i] == major) ? 1 : -1;
}
return major;
}
};
位操作
所有的数转成二进制形式,从低位向高位,遍历每个数字的相应位上的出现频率大于n/2的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;
}
};