169.求众数
https://leetcode-cn.com/problems/majority-element/
给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。
示例 1:
输入: [3,2,3]
输出: 3
示例 2:
输入: [2,2,1,1,1,2,2]
输出: 2
1.暴力法(python3:利用字典,其实跟hash表我觉得也一样)
c++想法类似,但是要麻烦一点,所以这里就不给c++的做法了
class Solution:
def majorityElement(self, nums: List[int]) -> int:
dict={}
for num in nums:
dict[num]=dict.get(num,0)+1
max=0
for num in nums:
if dict.get(num)>max:
max = dict.get(num)
if max>=(len(nums)+1)/2:
return num
2.排序
排序这样做法也是很有想法的,不管怎么样众数总是会出现在nums[nums.size()/2]这个位置上的
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(),nums.end());
return nums[nums.size()/2];
}
};
3.分治(会超时,不推荐,仅供参考)
这里我们使用经典的分治算法递归求解,直到所有的子问题都是长度为 1 的数组。由于传输子数组需要额外的时间和空间,所以我们实际上只传输子区间的左右指针 lo 和 hi 表示相应区间的左右下标。长度为 1 的子数组中唯一的数显然是众数,直接返回即可。如果回溯后某区间的长度大于 1 ,我们必须将左右子区间的值合并。如果它们的众数相同,那么显然这一段区间的众数是它们相同的值。否则,我们需要比较两个众数在整个区间内出现的次数来决定该区间的众数。原问题的答案就是下标为 000 和 nnn 之间的众数这一子问题。
class Solution {
public:
int majorityElement(vector<int>& nums) {
return helper(nums,0,nums.size()-1);
}
int count(vector<int>& nums,int l,int r,int num){
int count=0;
for(int i=l;i<r;i++){
if(nums[i]==num) count++;
}
return count;
}
int helper(vector<int>& nums,int l,int r){
if(l==r){
return nums[l];
}
int mid = (r-l)/2+l;
int leftz = helper(nums,l,mid);
int rightz = helper(nums,mid+1,r);
if(leftz==rightz) return leftz;
int leftcount = count(nums,0,nums.size()-1,leftz);
int rightcount = count(nums,0,nums.size()-1,rightz);
return leftcount>rightcount?leftz:rightz;
}
};
4.Boyer-Moore 投票算法(这种方法很巧妙,可以记一下)
class Solution {
public:
int majorityElement(vector<int>& nums) {
int count=0;
int candidate;
for(int i=0;i<nums.size();i++){
if(count==0){
candidate = nums[i];
}
if(nums[i]==candidate) count++;
else count--;
}
return candidate;
}
};