169.多数元素
写在前面,小白从零刷题,在解答会写出思路,正确答案,以及所有使用到的语法和知识点
1. 直接法 pass
- 思路就是找超到过一半的那个数字
- 当然这个对于特殊构造的例子可能不友好,时间复杂度为O(n^2)
class Solution {
public:
int majorityElement(vector<int>& nums) {
int n=nums.size();
for (auto i:nums)
{
int a=count(nums.begin(),nums.end(),i);//这个函数学会用
if(a>n/2)
return i;
}
return 0;
}
};
2.排序法 5
1.思路就是一旦一个数超过一半,那么排序后无论如何都在中间
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(),nums.end());
return nums[nums.size()/2];//值得借鉴的地方是思考一个数组排序后会如何
}
};
3.哈希表 2
1.思路就是把原来的vector容器放在哈希表里面,然后遍历数组,计算每一个出现的数的次数,保存到key中去,然后判断如果计算大于一半就停止遍历,这个可以同时进行,不需要先完全存好,可以一边查找一边遍历。
class Solution {
public:
int majorityElement(vector<int>& nums) {
unordered_map<int,int>ump;
for(auto i:nums)
{
if(++ump[i]>nums.size()/2)//unoredered_map的一开始初始化需要学习
return i;
}
return -1;
}
};
4.随机法 4
- 思路就是简单来说很关键的一个地方就是因为是众数,所以,我们采用随机法去大概率能找到符合要求的数,而且能规避一些特殊的数据
class Solution {
public:
int majorityElement(vector<int>& nums) {
while(1)
{
int candidate=nums[rand()%nums.size()];//对数组内取余不应该减1
if(count(nums.begin(),nums.end(),candidate)>nums.size()/2)
return candidate;
}
return -1;
}
};
5.分治法 未复习
1.思路就是将其分为两个数组,分别找到它们的众数,分治,花了一天的时间感觉有点浪费时间,哎,不知掉该怎么办,感觉没法想出来这个方法
class Solution {
public:
int majorityElement(vector<int>& nums)
{
int n=nums.size()-1;
int res=find_most(nums,0,n);
return res;
}
int find_most(vector<int>& nums,int low,int high)//定义形参,不是特别会
{
//分割到只有一个元素的时候
if(low==high) return nums[low];//如果左右不一致那么我们递归
//若有两个或者多个元素进入这个地方,我们首先进行分割
int mid=(low+high)/2;
int left_most=find_most(nums, low, mid);
int right_most=find_most(nums,mid+1,high);//分割数组
//分割之后计算每一部分的众数,
int left=count_most(nums,left_most,low,mid);
int right=count_most(nums,right_most,mid+1,high);
return left > right? left_most:right_most;//这个地方等于的时候无所谓,当等于的时候代表另外一部分一定是众数
}
int count_most(vector<int>&nums,int target,int l,int h)
{
int count=0;
for(int i=l;i<=h;i++)
{
if(target==nums[i])
count++;
}
return count;
}
};
6.摩尔投票法 5
- 摩尔投票法的关键在于将多数和少数分为战士的双方,选择开始的一个数,作为候选人,遇到该数加1,遇到异类减1,如果减到0,那么也没事,选择当时的数再次当选为候选人。总体的思路就是因为最后的数一定是候选人且>0.
class Solution {
public:
int majorityElement(vector<int>& nums) {
int candidate=0,count=0;
for(auto i:nums)
{
if(count==0) candidate=i;
if(candidate==i) count++;
if(candidate!=i) count--;
}
return candidate;
}
};
知识点及反思
- 遇到数组的一个新的思路就是思考一下排序后的情况会如何
- 哈希表用来查找和计数确实是一种比较好的方法
- 如果某个方法的某个代码看不懂,可以再看看别的同类型的代码
- 分治法总体来说感觉有点难想,之后再说吧
- 想不出来的题目,也要先看思路,看能否自己实现。
- 在刷题的时候,突然想到不应该用太多方法,起码在我刚起步的阶段不能使用多种方法,毕竟在面试中有可能遇到原题,所以应该先刷,其次,对一道题使用太多的方法会导致自己的成就感降低,所以暂时觉得应该先对每一道题,使用一种比较最优的方法和大众的方法。
- 另外一个思考就是我们应该用什么方法来去刷题呢,是按照数据结构的类型还是算法的类型呢