题目来源:

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.

Credits:
Special thanks to @ts for adding this problem and creating all test cases.

这道题在剑指offer上见到过,使用一次遍历的方式就可以求解。做完以后看了下Discuss,发现还有好多种解法。主要有下面这么多种,图片来自于这里

我针对其中的5种进行了实现,第1种由于时间复杂度太高没有实现,第4种由于存在最差的情况所以也没有实现。


解法一:Hash table

这种解法是使用一个hash表,键用来存放数组的元素,键对应的值存放元素出现的次数。遍历整个数组,查找它在hash表中是否出现,如果出现将出现次数加1,如果没有出现,将它插入hash表中,并设置它的出现次数为1。每次遍历到一个元素,判断它的出现次数是否超过了数组长度的一半,要是超过了就返回该元素。时间复杂度是O(n),空间复杂度是O(n)。。 
runtime:48ms

     int majorityElement(vector<int>& nums) {
if(nums.size()==1)
return nums[0];
map<int,int> tables;
for(int i=0;i<nums.size();i++)
{
if(tables.count(nums[i]))
{
tables[nums[i]]++;
if(tables[nums[i]]>nums.size()/2)
return nums[i];
}
else
{
tables[nums[i]]=1;
}
} }

解法二:Sorting

这种解法其实应该一开始就想到的,因为这种解法可以说是最简单的。对数组进行排序,那么出现次数超过一半的元素必定是数组中的中间元素,返回这个元素即可。时间复杂度是O(nlogn),空间复杂度是O(1)。 
runtime:40ms

class Solution{
int majorityElement(vector<int>&num){
sort(num.begin(),num.end());
return num(nums.size()/);
}
};

解法三:Divide and conquer

这道题的提示是使用分治法或位操作来求解,最开始我思考时也是把数组分成分成两部分,但是在原始数组中出现次数超过一半的元素不一定在子数组中出现次数超过一半,到这里就不知道如果进行后续的操作了。看了上面的解释发现正确的思考方法应该是这样的: 
将数组分成两部分,寻找第一个部分中出现次数超过一半的元素为A,第二个部分出现次数超过一半的元素为B,如果A==B,那么A就是这个数组中出现次数超过一半的元素,如果A!=B,那么A和B都可能是这个数组中出现次数超过一半的元素,那么重新遍历这个数组,记录A和B出现的次数,返回出现次数多的元素,时间复杂度T(n)=2T(n/2)+2n=O(nlogn)。

runtime:20ms

int majorityElement(vector<int>& nums) {

         return helper(nums,,nums.size()-);
} int helper(vector<int> &nums,int begin,int end)
{
if(begin==end)
return nums[begin];
if(begin<end)
{
int mid=begin+(end-begin)/;
int left=helper(nums,begin,mid);
int right=helper(nums,mid+,end);
if(left==right)
return left;
else
{
int leftCount=;
int rightCount=;
for(int i=begin;i<=end;i++)
{
if(nums[i]==left)
leftCount++;
else if(nums[i]==right)
rightCount++;
} if(leftCount<rightCount)
return right;
else if(leftCount>rightCount)
return left;
}
}
}

解法四:Moore voting alogrithm

这种解法就是在《剑指offer》上看到的那种解法。它本质上也是一种分治法,只不过在编程时使用了一些技巧,结果没那么容易看出来了。 
算法的思想如下:每次从数组中找出一对不同的元素,将它们从数组中删除,直到遍历完整个数组。由于这道题已经说明一定存在一个出现次数超过一半的元素,所以遍历完数组后数组中一定会存在至少一个元素。 
上面就是这种算法的思想,删除操作可以在常数时间内完成,但是查找不同的元素无法在常数时间内完成,这里有一个技巧。 
在算法执行过程中,使用常量空间来记录一个候选元素c以及它的出现次数f(c),c即为当前阶段出现次数超过一半的元素。在遍历开始之前,该元素c为空,f(c)=0。然后开始遍历数组A时:

  1. 如果f(c)为0,表示当前并没有候选元素,也就是说之前的遍历过程中没有找到超过一半的元素。那么,如果超过一半的元素c存在,那么c在剩下的子数组中,出现的次数也一定超过一半。因次我们可以将原始问题转化成它的子问题。此时c赋值为当前元素,同时f(c)=1。
  2. 如果当前A[i]==c,那么f(c)+=1。(没有找到相同的元素,只需要把相同的元素累加起来)
  3. 如果当前元素A[i]!=c,那么f(c)-=1(相当于删除一个c),不对A[i]做任何处理(相当于删除A[i]) 
    如果遍历结束之后,f(c)不为0,那么再次遍历一遍数组,如果c真正出现的频率,上面算法的时间复杂度是O(n),空间复杂度为O(1)。这种方法的分析来自这里

runtime:20ms

   int majorityElement(vector<int>& nums) {
int count=;
int result=nums[];
for(int i=;i<nums.size();i++)
{
if(count==||nums[i]==result)
{
count++;
result=nums[i];
}
else
count--;
}
return result;
}

解法五:Bit manipulation

还可以使用位操作来求解这道题。因为一个整数在32为机器上只有32位,那么可以使用一个长度为32的数组来记录输入数组中每1位中1的个数和0的个数,由于存在一个出现次数超过一半的元素,那么取第i位中出现次数多的(0或者1)即可以构成超过数组一半元素。 
runtime:40ms

int majorityElement(vector<int>& nums) {
int **table=new int*[];
int result=;
for(int i=;i<;i++)
{
table[i]=new int[]();
}
for(int i=;i<nums.size();i++)
{
for(int j=;j<;j++)
{
int pos=<<j&nums[i]?:;
table[j][pos]++;
}
}
for(int i=;i<;i++)
{
if(table[i][]>table[i][])
result+=<<i;
}
return result;
}

LeetCode169:Majority Element(Hash表\位操作未懂)的更多相关文章

  1. LeetCode169 Majority Element, LintCode47 Majority Number II, LeetCode229 Majority Element II, LintCode48 Majority Number III

    LeetCode169. Majority Element Given an array of size n, find the majority element. The majority elem ...

  2. leetcode169——Majority Element (C++)

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

  3. [LeetCode169]Majority Element求一个数组中出现次数大于n/2的数

    题目: Given an array of size n, find the majority element. The majority element is the element that ap ...

  4. [LeetCode169]Majority Element

    Majority Element Total Accepted: 58500 Total Submissions: 163658My Submissions Question Solution  Gi ...

  5. [Swift]LeetCode169. 求众数 | Majority Element

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

  6. [LeetCode] Majority Element 求众数

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

  7. [LeetCode] Majority Element 求大多数

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

  8. PHP数组/Hash表的实现/操作、PHP变量内核实现、PHP常量内核实现 - [ PHP内核学习 ]

    catalogue . PHP Hash表 . PHP数组定义 . PHP变量实现 . PHP常量实现 1. PHP Hash表 0x1: 基本概念 哈希表在实践中使用的非常广泛,例如编译器通常会维护 ...

  9. Hash表的扩容(转载)

    Hash表(Hash Table)   hash表实际上由size个的桶组成一个桶数组table[0...size-1] . 当一个对象经过哈希之后.得到一个对应的value , 于是我们把这个对象放 ...

随机推荐

  1. Konckout第二个实例:数组数据类型双向绑定 -- 下拉select

    自定义js做法: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> &l ...

  2. New UWP Community Toolkit - XAML Brushes

    概述 上一篇 New UWP Community Toolkit 文章中,我们对 V2.2.0 版本的重要更新做了简单回顾.接下来会针对每个重要更新,结合 SDK 源代码和调用代码详细讲解. 本篇我们 ...

  3. WebAPI问题追踪日志记录过滤器

    公司项目比较坑爹,毕竟涉及到前后端分离.多部门协作,很多时候系统出问题,哪怕已经很清楚了,协作方依然要我们把API调用入参.响应等记录下来,而且是全记录,不光是异常调用,待调查结束后这些日志又需要卸下 ...

  4. Eclipse配置类似sublime的黑色主题

    另一篇中,详细介绍了如何使用Eclipse+Pydev搭建Python环境,传送门:http://www.cnblogs.com/BH8ANK/p/8688110.html 下面介绍下如何在Eclip ...

  5. android 与 服务器通信

    android 与 服务器通信 服务端代码: (1)control 层 /** * 用户登录 * @return */ @RequestMapping(value = "/login&quo ...

  6. 个人总结——Beta阶段

    Beta总结 我们在beta 结束之后, 每位写一个博客, 回顾并总结自己的beta过程,哪些方面做的好的,哪些方面做得不足需要改进的 回答问题 分析在Alpha阶段自己提出的五个问题,针对每个问题, ...

  7. splinter web测试框架

    1.安装谷歌浏览器驱动(windows把驱动解压放在Python.exe同级目录即可) http://chromedriver.storage.googleapis.com/index.html 注意 ...

  8. 【Swift】iOS导航栏错乱的原因

    #iOS开发高级技巧#导航栏错乱,也就是导航栏的显示效果与内容区不匹配,引发原因很多,其中最重要的有两个原因: 1.在viewwillappear,viewwilldisappear两个函数中,设置导 ...

  9. aws中的路由表

    参考官方文档: 由表中包含一系列被称为路由的规则,可用于判断网络流量的导向目的地. 在您的 VPC 中的每个子网必须与一个路由表关联:路由表控制子网的路由.一个子网一次只能与一个路由表关联,但您可以将 ...

  10. Hyper-V虚拟机故障导致数据文件丢失的数据恢复全过程

    简介: 由于MD3200存储中虚拟机的数据文件丢失,导致整个Hyper-V服务瘫痪,虚拟机无法使用,故障环境为Windows Server 2012服务器,系统中部署了Hyper-V虚拟机环境,虚拟机 ...