LeetCode169:Majority Element(Hash表\位操作未懂)
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时:
- 如果f(c)为0,表示当前并没有候选元素,也就是说之前的遍历过程中没有找到超过一半的元素。那么,如果超过一半的元素c存在,那么c在剩下的子数组中,出现的次数也一定超过一半。因次我们可以将原始问题转化成它的子问题。此时c赋值为当前元素,同时f(c)=1。
- 如果当前A[i]==c,那么f(c)+=1。(没有找到相同的元素,只需要把相同的元素累加起来)
- 如果当前元素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表\位操作未懂)的更多相关文章
- 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 ...
- leetcode169——Majority Element (C++)
Given an array of size n, find the majority element. The majority element is the element that appear ...
- [LeetCode169]Majority Element求一个数组中出现次数大于n/2的数
题目: Given an array of size n, find the majority element. The majority element is the element that ap ...
- [LeetCode169]Majority Element
Majority Element Total Accepted: 58500 Total Submissions: 163658My Submissions Question Solution Gi ...
- [Swift]LeetCode169. 求众数 | Majority Element
Given an array of size n, find the majority element. The majority element is the element that appear ...
- [LeetCode] Majority Element 求众数
Given an array of size n, find the majority element. The majority element is the element that appear ...
- [LeetCode] Majority Element 求大多数
Given an array of size n, find the majority element. The majority element is the element that appear ...
- PHP数组/Hash表的实现/操作、PHP变量内核实现、PHP常量内核实现 - [ PHP内核学习 ]
catalogue . PHP Hash表 . PHP数组定义 . PHP变量实现 . PHP常量实现 1. PHP Hash表 0x1: 基本概念 哈希表在实践中使用的非常广泛,例如编译器通常会维护 ...
- Hash表的扩容(转载)
Hash表(Hash Table) hash表实际上由size个的桶组成一个桶数组table[0...size-1] . 当一个对象经过哈希之后.得到一个对应的value , 于是我们把这个对象放 ...
随机推荐
- java高并发锁的三种实现
提到锁大家会想到Synchronized同步关键字,使用它确实可以解决一切并发问题,但是对于体统吞吐量要求更高,在这里提供了几个小技巧.帮助大家减少锁粒度.提高系统的并发能力 一.乐观锁 试用场景:读 ...
- kvm之四:从网上镜像安装虚拟机Centos6.8
1.再加块硬盘,格式化挂载至新建目录/kvm2下 2.CentOS 6.8镜像地址 http://mirrors.163.com/centos/6.8/os/x86_64/ 3.配置安装参数,执行安装 ...
- android中activity.this跟getApplicationContext的区别
转载: http://www.myexception.cn/android/1968332.html android中activity.this和getApplicationContext的区别 在a ...
- New UWP Community Toolkit - RadialProgressBar
概述 UWP Community Toolkit 中有一个圆形的进度条控件 - RadialProgressBar,本篇我们结合代码详细讲解 RadialProgressBar 的实现. Radi ...
- iPhone的App嵌入html页面问题
测试环境:iPhone ios 11.0.3 问题:iPhone App嵌入HTML页面,页面拉动到底部时,手势从屏幕底部边缘开始往上拉动,页面出现白色图层,且html页面一屏外的会卡住,无法滚动,需 ...
- bug终结者 团队作业第三周
bug终结者 团队作业第三周 团队展示 队名 bug终结者 队员风采: 杨京典 20162302 风格:先构建框架,在一 一实现,在实现的过程中不断测试和修改. 擅长的技术:拆分问题,使用相对简单的思 ...
- python的测试
测试 知识点 单元测试概念 使用 unittest 模块 测试用例的编写 异常测试 测试覆盖率概念 使用 coverage 模块 实验步骤 1. 应该测试什么? 如果可能的话,代码库中的所有代码都要测 ...
- 大神都在看的RxSwift 的完全入坑手册
大神都在看的RxSwift 的完全入坑手册 2015-09-24 18:25 CallMeWhy callmewhy 字号:T | T 我主要是通过项目里的 Rx.playground 进行学习和了解 ...
- Struts2之Struts2的下载与安装
Struts2的下载 登陆struts的官网 下载Full Distribution这个选项的struts2的包. 这是Struts2的完整版,里面包括Struts2的实例应用,空实例应用,核心库,源 ...
- Apache的配置httpd.conf文件配置
(1) 基本配置: ServerRoot "/mnt/software/apache2" #你的apache软件安装的位置.其它指定的目录如果没有指定绝对路径,则目录是相对于该目录 ...