力扣169题,多数元素

力扣169题,多数元素

题目描述

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

输入输出样例

输入:nums = [3,2,3]
输出:3
输入:nums = [2,2,1,1,1,2,2]
输出:2

tips

  • n == nums.length
  • 1 <= n <= 5 * 104
  • -109 <= nums[i] <= 109
  • **进阶:**尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。

解法一,使用hash

  int majorityElement(vector<int>& nums) 
        {
            //判断是否为空
            if(nums.empty())
            {
                return NULL;
            }
            //建立hash表保存数据
            unordered_map<int,int>umap;

            //将数组中的数字保存进hash表中
            for(auto i:nums)
            {
                if(umap.count(i))
                {
                    umap[i]=umap[i]+1;
                }
                else{
                   umap[i]=0;
                }
            }

            //寻找多数元素
            int length=nums.size();

            for(auto i=umap.cbegin();i!=umap.cend();i++)
            {
                if(i->second>=(length/2))
                {
                    return i->first;
                }

            }
            return NULL;
        }

解法2,排序


        //解法2,使用排序的方法,因为多数元素他一定出现在中间
        //时复 O(nlogn) 空复 O(logn)
         int majorityElement2(vector<int>& nums)
         {
            sort(nums.begin(),nums.end());
            int length=nums.size();
            return nums[length/2];
         }

解法3,循环

 //解法3,使用随机的方法,随机选择一个数字,如果其出现的次数大于n/2,则可以返回
         //时复 最坏 O(无穷) 期望是 O(n) 空复 O(1)
         int majorityElement3(vector<int>& nums)
         {
            while(true)
            {
                int candidate=nums[rand()%nums.size()];
                int count=0;

                for(auto i:nums)
                {
                    if(i==candidate)
                    {
                        count+=1;
                    }
                }

                if(count>nums.size()/2)
                {
                    return candidate;
                }
            }
         }

解法四,分治

         //解法4,使用分治法的思想,若数字n是总数,那么其必定是其一部分的众数
         //时复 O(nlogn) 空复 O(logn)
          int majorityElement4(vector<int>& nums)
          {
            return majorityElementRec(nums,0,nums.size()-1);
          }

          int majorityElementRec(vector<int>&nums,int lo,int hi)
          {
            //如果最后的数组个数为1,则当前值必为最多数
            if(lo==hi)
            {
                return nums[lo];
            }
            //mid 取区间中值
            int mid=(lo+hi)/2;
            int leftMajority=majorityElementRec(nums,lo,mid);
            int rightMajority=majorityElementRec(nums,mid+1,hi);

            //判断该值是否是整个大区间的最大数
            if(countInRange(nums,leftMajority,lo,hi)>(hi-lo+1)/2)
            {
                return leftMajority;
            }
            if(countInRange(nums,rightMajority,lo,hi)>(hi-lo+1)/2)
            {
                return rightMajority;
            }
            return -1;

          }

           int countInRange(vector<int>&nums,int target,int lo,int hi)
           {
                int count=0;
                for(int i=lo;i<=hi;i++)
                {
                    if(nums[i]==target)
                    {
                        count++;
                    }
                }
                return count;
           } 

解法5,投票法

//解法5,使用投票法进行处理,将最大数记为+1,其余不相同的数则将-1,则最后结果相加必大于0
            //时复 O(n) 空复 O(1)
            int majorityElement5(vector<int>& nums)
            {
                int candidate=-1;
                int count=0;

                //遍历数组,类似于动态规划的方法
                for(int num:nums)
                {
                    //当值与候选值相等的时候,则计数增加
                    if(num==candidate)
                    {
                        ++count;
                    }
                    //若值与候选值不相等,且其累计获得的票数小于0,则重新选定候选值
                    //因为对于大于一半存在的最大数而言,其必定正的要大于负的
                    else if(--count<0)
                    {
                        candidate=num;
                        count=1;
                    }
                }
                return candidate;
            }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值