Problem:
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.
…
Solution 1:
虽然是按照分类选择的,但首先想到的并不是分治算法。这里也先写下来,以便进行比较。
算法分为两部分:第一部分遍历向量用map记录每个元素出现的次数,遍历的复杂度为O(n),map的find方法复杂度为O(logm),m为不同key数目,总复杂度为O(nlogm)。第二部分再次遍历,找到出现次数大于n/2的元素并返回,时间复杂度为O(n)。因此算法整体时间复杂度为O(nlogn),使用了map,空间复杂度为O(n),代码如下:
#include <map>
using namespace std;
class Solution {
public:
int majorityElement(vector<int>& nums) {
map<int, int> ans;
for (int i = 0; i < nums.size(); ++i){
if (ans.find(nums[i])==ans.end())
ans[nums[i]] = 1;
else
ans[nums[i]]++;
}
for (int i = 0; i < nums.size(); ++i){
if (ans[nums[i]] > nums.size()/2)
return nums[i];
}
return 0; // 有约束条件ME一定存在,所以可返回任意值,否则要对不存在的情况特殊处理
}
};
LeetCode上的测试时间为39ms. 在某些情况下,比如1,1,2,2,3,3,3,3,3,第二次遍历的过程中可能重复比较同一个非ME的key的value. 因为结果唯一,也可以用multimap,和map的查找复杂度相当。此时第二部分时间复杂度变为O(m),对给定测试用例有一定优化,36ms,但算法复杂度仍为O(nlogm),只是实现略有不同.
#include <map>
using namespace std;
class Solution {
public:
int majorityElement(vector<int>& nums) {
multimap<int, int> ans;
for (int i = 0; i < nums.size(); ++i){
if (ans.find(nums[i])==ans.end())
ans.insert(make_pair(nums[i], 1));
else
(ans.find(nums[i]))->second++;
}
for (multimap<int,int>::iterator i = ans.begin(); i != ans.end(); i++){
if ((*i).second > nums.size()/2)
return (*i).first;
}
return 0;
}
};
…
Solution 2:
因为ME数目一定大于n/2,所以可以将向量排序,中值一定是ME。调用sort函数,其底层是一种混合排序;自己写可以使用归并排序(分治算法)或者堆排序,时间复杂度都为O(nlogn). LeetCode测试时间为36ms.
#include <algorithm>
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(),nums.end());
return nums[nums.size()/2];
}
};
…
Solution 3:
在Discuss中学习到了很巧妙的算法Boyer–Moore majority vote algorithm,本问题中时间复杂度为O(n),空间复杂度为O(1).
算法将每对相邻元素进行比较,count=0时更新maj,count++;元素相同时count++;不同时count–。无论从ME还是非ME元素开始执行算法,由于ME数多于非ME,都有一个时间点t,t以后的maj一直是ME. LeetCode测试时间为16ms.
class Solution {
public:
int majorityElement(vector<int>& nums) {
int maj = nums[0], count = 1;
for (int i = 1; i < nums.size(); ++i){
if (count == 0){
maj = nums[i];
count++;
}
else if (nums[i] == maj)
count++;
else
count--;
}
return maj;
}
};
原代码链接 https://discuss.leetcode.com/topic/8692/o-n-time-o-1-space-fastest-solution
算法链接 https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_majority_vote_algorithm