LeetCode169—MajorityElements

来源:互联网 发布:网络新闻发言人 编辑:程序博客网 时间:2024/05/21 23:43

LeetCode169—MajorityElements

原题

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element always exist in the array.

在一个数组中找到出现次数大于n/2的“多数派”元素。

题目的前提是,一定存在这样的多数派元素,如果不存在的话也可以求出来。

西电计院的同学应该对这个题还有比较深刻的印象,就是算法考试中的,呵呵~


分析1

如果对时间复杂度没有要求的话,这个题目最简单的做法对元素先进行排序。
排序完的序列索引为n/2的元素肯定是出现次数超过半数的元素。

代码1

class Solution{    public:        int majorityElement( vector<int>&nums );};int Solution::majorityElement( vector <int> &nums ){   sort(nums.begin(),nums.end());//排序   int n = nums.size();   return nums[n/2];}

分析2

std::sort()的时间复杂度为O(nlogn),当然也可以自己写一个线性时间复杂度内的counting-sort,但是感觉意义不大,虽然思想差不错,我们有更好的办法将时间复杂度控制在O(n)范围内,那就是直接用HashMap了。
这样我们只需要两次线性扫描:
前提是建立一个hashmap,key为数组中的元素,value为他们出现的次数
第一次,统计每个元素的出现次数,map[key]=map[key]+1;
第二次,返回超过半数的key即可。

代码2

class Solution{    typedef unordered_map<int,int>::iterator iterator;//迭代器类型    public:        int majorityElement( vector<int>&nums );};int Solution::majorityElement( vector<int> &nums ){    unordered_map<int,int>myMap;    for(int i = 0 ; i < nums.size(); i++)     {        myMap[nums[i]]= myMap[nums[i]]+1;    }//统计/* 1.要么直接访问    for(int i = 0 ; i < nums.size(); i++)     {        if(myMap[nums[i]] >= (nums.size()+1)/2)            return nums[i];    }*///2.或者用迭代器访问    for( iterator it = myMap.begin();it!=myMap.end(); it++)    {        if( (*it).second >= (nums.size()+1)/2 )            return (*it).first;    }    return -1;//如果没有超过半数的元素}

分析3

上述分析2已经将时间复杂度控制在线性条件下了,但是空间复杂度增加,这是用空间换取时间的典型方法,接下来要介绍的算法就牛逼了,它的空间也能控制在O(1)条件下。

这个算法叫做:Boyer–Moore majority vote algorithm

其思想说明一下:

1.首先,假设一个数组[A A B C A D A E A],如果让人来做这件事请,我们会删去两两不同的元素(不管我们采取哪种组合,只要是两两不同即可),删到最后剩下的就是我们需要的元素。本例中即A
2.但是,对于计算机来说,它只能从头到尾对数组进行遍历,没有办法去挑两两不同的元素,为了模拟上述过程,我们定义一个count和一个表示当前可能成为“多数派”的元素candidate。
3.在一次扫描中,如果元素和当前candidate相同则count++,不同则count–,表示删除一对两两不同元素,当count减为0时,我们就需要更新我们的candidate了。
4.如果还要考虑不存在多数派的情况,最后还需要进行一点小处理。这部分在代码中说明

这个算法的发明者提供了一个算法的单步演示:演示链接

代码3

int Solution::majorityElement (vector<int> & nums){    int candidate = nums[0];    int count =0;    for(int i=0; i < nums.size(); i++ )    {        if(count == 0)//重新选择candidate        {            count = 1;            candidate = nums[i];        }        else        {            count = candidate==nums[i]?(count+1):(count-1);        }    }    //下面代码排除没有多数派情况    count = 0;    for (int i =0;i<nums.size(); i++)     {        if (nums[i] == candidate)             count++;    }    if (count < (nums.size() + 1) / 2)         return -1;    return candidate;}

判断是否存在多数派的思想就是看最后的candidate的个数是否超过n/2,当然时间复杂度也是线性的。

2 0
原创粉丝点击