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.

思路:

Find k different element, and “remove” them as a group, the remaining element must be the element that appears more than ⌊n/k⌋ times. (Detailed explanation is given in comment)

In this problem, k equals to 2.

Thus we “remove” each pair of 2 different elements, and the remaining element that do not have its counterpart is the desired element.

时间复杂度O(n)空间复杂度O(1)的算法呢? 实际上,早在91年就有人专门就这个问题发表了论文,介绍了一种线性时间的算法: Majority Vote Algorithm。通过名字就可以看出,这个算法是专门用来解决这个问题的。而由于作者是J Moore (目前是Utexas的计算机系主任),这个算法有时候也会被称为Moore’s Voting Algorithm (当然这个Moore并不是提出Moore’s Law的那个Gordon Moore)。

算法的基本思想非常简洁: 每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。 不难证明,如果存在元素e出现频率超过半数,那么数组中最后剩下的就只有e。当然,最后剩下的元素也可能并没有出现半数以上。比如说数组是[1, 2, 3],最后剩下的3显然只出现了1次,并不到半数。排除这种false positive情况的方法也很简单,只要保存下原始数组,最后扫描一遍验证一下就可以了。

现在来分析一下复杂度。删除元素可以在常数时间内完成,但找不同元素似乎有点麻烦。实际上,我们可以换个角度来想,用一个小trick来重新实现下该算法。

在算法执行过程中,我们使用常量空间实时记录一个候选元素c以及其出现次数f(c),c即为当前阶段出现次数超过半数的元素。在遍历开始之前,该元素c为空,f(c)=0。然后在遍历数组A时,

如果f(c)为0,表示当前并没有候选元素,也就是说之前的遍历过程中并没有找到超过半数的元素。那么,如果超过半数的元素c存在,那么c在剩下的子数组中,出现次数也一定超过半数。因此我们可以将原始问题转化为它的子问题。此时c赋值为当前元素, 同时f(c)=1。
如果当前元素A[i] == c, 那么f(c) += 1。(没有找到不同元素,只需要把相同元素累计起来)
如果当前元素A[i] != c,那么f(c) -= 1 (相当于删除1个c),不对A[i]做任何处理(相当于删除A[i])

如果遍历结束之后,f(c)不为0,那么再次遍历一遍数组,记录c真正出现的频率,从而验证c是否真的出现了超过半数。上述算法的时间复杂度为O(n),而由于并不需要真的删除数组元素,我们也并不需要额外的空间来保存原始数组,空间复杂度为O(1)。实际上,在Moore大牛的主页上有针对这个算法的一个演示,感兴趣的同学可以直接移步观看。

这个问题看上去已经完美的解决了。

二、更一般的情况呢?

那么,如果我们想找的并不是超过半数的元素,而是出现频率超过一定频率的元素都要找出来,是否也存在一个类似的线性时间的算法呢?答案是肯定的。实际上,这一类从特定的数据集中找出出现频率超过某个阈值的元素的问题,有一个形象的名字叫做Iceberg query,或者叫做host list分析。而Richard Karp 老爷子当年就专门写了一篇论文来讨论这种一般性问题的解决方案,而通过下文的介绍,大家也可以发现,Karp的方案应该也是受到了Moore的算法的启发。

首先还是看一下问题的形式化定义吧:

对于一个序列 以及一个在(0,1)之间的实数。假定表示元素的出现频率,我们需要找到所有满足的元素。

原帖连接:

https://leetcode.com/discuss/19151/solution-computation-space-problem-can-extended-situation

http://m.blog.csdn.net/blog/wenyusuran/40780253

解决方案:

class Solution {
public:
int majorityElement(vector<int>& nums)
{
int size = nums.size();
int vote = 0;
int count = 0; for(int i = 0;i < size;i++)
{
if(count == 0)
{
vote = nums[i];
count = 1;
}
else
{
if(vote == nums[i])
count++;
else
count--;
}
}
return vote;
}
};

STL解决方案:

int majorityElement(vector<int> &num)
{
map<int, int>count;
for (vector<int>::iterator i = num.begin(); i != num.end();i++)
{
if ( (++count[*i]) > num.size() / 2)
return *i; }
}

c语言:

int majorityElement(int num[], int n)
{
int cnt = 0, res;
for (int i = 0; i < n; ++i)
{
if (cnt == 0) res = num[i];
if (res == num[i]) ++cnt;
else --cnt;
}
return res;
}

python解决方案:

class Solution:
# @param {integer[]} nums
# @return {integer}
def majorityElement(self, nums):
count = {}
for i in nums:
if i not in count:
count[i] = 0
count[i] += 1
if count[i] > len(nums)/2:
return i

leetcode 169 Majority Element 冰山查询的更多相关文章

  1. leetcode 169. Majority Element 、229. Majority Element II

    169. Majority Element 求超过数组个数一半的数 可以使用hash解决,时间复杂度为O(n),但空间复杂度也为O(n) class Solution { public: int ma ...

  2. 23. leetcode 169. Majority Element

    169. Majority Element Given an array of size n, find the majority element. The majority element is t ...

  3. Leetcode#169. Majority Element(求众数)

    题目描述 给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是非空的,并且给定的数组总是存在众数. 示例 1: 输入: [3,2,3] ...

  4. [LeetCode] 169. Majority Element 多数元素

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  5. LeetCode 169. Majority Element (众数)

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  6. LeetCode 169. Majority Element - majority vote algorithm (Java)

    1. 题目描述Description Link: https://leetcode.com/problems/majority-element/description/ Given an array ...

  7. ✡ leetcode 169. Majority Element 求出现次数最多的数 --------- java

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  8. LeetCode 169. Majority Element

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  9. Java for LeetCode 169 Majority Element

    Given an array of size n, find the majority element. The majority element is the element that appear ...

随机推荐

  1. python中的函数(定义、多个返回值、默认参数、参数组)

    函数定义 在python中函数的定义以及调用如下代码所示: def test(x): y = x+1 return y result = test(2) print(result) 多个返回值的情况 ...

  2. CSDN没有审核投诉的真实性直接删除博主上传的资源

      今天打开博客,发现一条未读通知:您上传的资源* * * *因质量投诉没有通过审核,如有疑问,请联系webmaster@csdn.net 我马上去看了下我的资源下载页,资源已经被删除,积分也已清空- ...

  3. Programming In Scala笔记-第十一章、Scala中的类继承关系

    本章主要从整体层面了解Scala中的类层级关系. 一.Scala的类层级 在Java中Object类是所有类的最终父类,其他所有类都直接或间接的继承了Object类.在Scala中所有类的最终父类为A ...

  4. leetcode 5 Longest Palindromic Substring--最长回文字符串

    问题描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...

  5. Android属性动画完全解析(下),Interpolator和ViewPropertyAnimator的用法

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/44171115 大家好,欢迎继续回到Android属性动画完全解析.在上一篇文章当中 ...

  6. Spark:聚类算法

    Spark:聚类算法 Kmeans聚类 KMeans算法的基本思想是初始随机给定K个簇中心,按照最邻近原则把待分类样本点分到各个簇.然后按平均法重新计算各个簇的质心,从而确定新的簇心.一直迭代,直到簇 ...

  7. 剑指Offer——网易笔试题+知识点总结

    剑指Offer--网易笔试题+知识点总结 Fibonacci package cn.edu.ujn.nk; import java.util.ArrayList; import java.util.S ...

  8. Android TV开发总结(六)构建一个TV app的直播节目实例

    请尊重分享成果,转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52966319 近年来,Android TV的迅速发展,传统的有线电视受 ...

  9. Linux Java开发坏境搭建,Ubuntu-jdk+tomcat+eclipse+svn 包安装详细操作

    更新时间2015-03-15 更新2015-04-12 svn安装更新 第一步 安装jdk (在linux上使用yum安装JDK  http://blog.chinaunix.net/uid-1546 ...

  10. Afinal加载网络图片及下载文件使用方法

    Afinal快速开发框架使用起来非常方便,下面将讲解如何利用Afinal加载网络图片及下载文件: 先看效果图: 注意:使用Afinal前需添加Afinal的jar,可以在这里下载:http://dow ...