169. 多数元素 c++实现 6种方法

169.多数元素

写在前面,小白从零刷题,在解答会写出思路,正确答案,以及所有使用到的语法和知识点

1. 直接法 pass

  1. 思路就是找超到过一半的那个数字
  2. 当然这个对于特殊构造的例子可能不友好,时间复杂度为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

  1. 思路就是简单来说很关键的一个地方就是因为是众数,所以,我们采用随机法去大概率能找到符合要求的数,而且能规避一些特殊的数据
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,遇到异类减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;
    }
};

知识点及反思

  1. 遇到数组的一个新的思路就是思考一下排序后的情况会如何
  2. 哈希表用来查找和计数确实是一种比较好的方法
  3. 如果某个方法的某个代码看不懂,可以再看看别的同类型的代码
  4. 分治法总体来说感觉有点难想,之后再说吧
  5. 想不出来的题目,也要先看思路,看能否自己实现。
  6. 在刷题的时候,突然想到不应该用太多方法,起码在我刚起步的阶段不能使用多种方法,毕竟在面试中有可能遇到原题,所以应该先刷,其次,对一道题使用太多的方法会导致自己的成就感降低,所以暂时觉得应该先对每一道题,使用一种比较最优的方法和大众的方法。
  7. 另外一个思考就是我们应该用什么方法来去刷题呢,是按照数据结构的类型还是算法的类型呢
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值