Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.(给定一个大小为n 的数组,找出其中数量占大多数的元素,这个元素 的个数会大于 [n/2])
You may assume that the array is non-empty and the majority element always exist in the array.(
可以假设这是一个非空数组,并且主元素一定存在)
Example 1:
Input: [3,2,3]
Output: 3
Example 2:
Input: [2,2,1,1,1,2,2]
Output: 2
题解:
Solution 1:
最直接的想法是遍历数组将每个元素出现的次数记录下来,这里将次数作为value存在map里面,map中的 key 是这个元素本身,如果想要性能优化,可以使用unordered_map,因为 map内部是红黑树在插入的过程中会自动排序,而unordered_map内部是散列表,不会排序,所以更省时间。
然后再遍历这个Map, 一旦找到个数超过n/2的元素就可以返回了。
class Solution {
public:
int majorityElement(vector<int>& nums) {
map<int,int> elements;
for(int i=0;i<nums.size();i++)
{
if(elements.find(nums[i])!=elements.end())
{
elements[nums[i]]=elements[nums[i]]+1;
}
else{
elements[nums[i]]=1;
}
}
map<int,int>::iterator it;
for(it=elements.begin();it!=elements.end();it++)
{
if(it->second>nums.size()/2) return it->first;
}
return 0;
}
};
复杂度分析: 总体时间复杂度是O(n), 空间复杂度也是O(n);
Solution 2:
这是一种最简洁的方法,利用占大多数那个元素个数大于[n/2]的性质,先将原来的数组排序,排序之后的数组位于正中间的元素一定是那个占大多数的元素。
class Solution {
public:
int majorityElement(vector<int>& nums) {
std::sort(nums.begin(),nums.end());
return nums[nums.size()/2];
}
};
复杂度分析,这里主要是sort函数的复杂度。
时间复杂度:由于sort的底层实现在数组元素较少的时候使用插入排序(O(n)),元素较多的时候使用快速排序O(nlogn),
空间复杂度:插入排序(O(1)),快速排序O(1).
Solution 3:
摩尔投票算法:
将数组里面的数据分成两类,一类是元素个数最多的元素,也就是我们关心的元素;另一类是其他的元素。就像是在进行选举,我们要选到票数超过一半的候选人。
开始并不知道谁是个数最多的,那么假设第一元素是,然后如果后面出现了这个元素,则让他的票数加一,否则,就让票数减一,知道他的票数变为0, 就更换下一个候选人,这样遍历完所有的数组之后,剩下的就是那个得最多票数的了。
class Solution {
public:
int majorityElement(vector<int>& nums) {
int candidate=nums[0];
int count=0;
for(int i=0;i<nums.size();i++)
{
if(count == 0) candidate = nums[i];
if(nums[i]!=candidate) count--;
else{
count++;
}
}
return candidate;
}
};
复杂度分析: 时间复杂度O(n) 空间复杂度O(1);
Solution 4:
分治法:
递归的找出左边数量最多的元素和右边数量最多的元素,如果两者相同,则是全局最多数;如果两者不同,则再遍历数组比较两者在全局中哪个更多。
class Solution {
public:
int majorityElement(vector<int>& nums) {
return find(nums,0,nums.size()-1);
}
int find(vector<int>& nums, int low, int high)
{
if(low==high)
return nums[low];
int mid = low + (high-low)/2;
int left = find(nums,low,mid);
int right = find(nums,mid+1,high);
if(left==right)
return left;
else{
int leftCount=0;
int rightCount=0;
for(int i=0;i<nums.size();i++)
{
if(nums[i]==left) leftCount++;
if(nums[i]==right) rightCount++;
}
return leftCount>rightCount? left:right;
}
}
};
复杂度分析: 时间复杂度O(n), 空间复杂度O(1).