leetcode题解 169. Majority Element 求大多数的元素

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).

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值