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 , 于是我们把这个对象放 ...
随机推荐
- postman简单教程-环境变量,全局变量的设置及作用
讲postman环境变量设置之前,先讲一个小插曲,环境变量.全局变量的区别在于Globals,只能用一组,而Environmen可以设置多组,所以我更喜欢设置环境变量 1.环境变量-Environme ...
- cookie session的共同点和区别
由于HTTP协议是无状态的,在WEB系统中,怎么识别请求来自于哪里呢?是哪一个用户发起的请求呢? 为了解决这一个问题, HTTP协议引入了cookie和session这两个概念 cookie是服务器传 ...
- WEB 表格测试点
Web页面的表格测试点: 1.表格列名 2.表格翻页.表格跳转到多少页.最后一页.首页 3.表格每页显示的数据, 数据的排序 4.表格无数据 5.表格支持的最大数据量 6.表格中数据内容超长时,显示是 ...
- SSH三大框架整合案例
SSH三大框架的整合 SSH三个框架的知识点 一.Hibernate框架 1. Hibernate的核心配置文件 1.1 数据库信息.连接池配置 1.2 Hibernate信息 1.3 映射配置 ...
- JDK1.8源码(六)——java.util.LinkedList 类
上一篇博客我们介绍了List集合的一种典型实现 ArrayList,我们知道 ArrayList 是由数组构成的,本篇博客我们介绍 List 集合的另一种典型实现 LinkedList,这是一个有链表 ...
- beta冲刺 用户使用调查报告
测评结果 一.使用体验 数据加载响应很快,页面切换丝滑流畅. UI有点偏暗,有些字被覆盖了. 页面布局过于居中,两侧空白范围较大. 总体功能完善. 二.登录.注册.忘记密码界面 管理员登录按钮太靠下, ...
- NumPy简介
NumPy是什么? NumPy(Numerrical Python 的缩写)是一个开源的Python科学计算库.使用NumPy,就可以很自然的使用数组.NumPy包含很多实用的数学函数,涵盖线性代数运 ...
- Beta冲刺Day3
项目进展 李明皇 今天解决的进度 完善了程序的运行逻辑(消息提示框等) 明天安排 前后端联动调试 林翔 今天解决的进度 向微信官方申请登录验证session以维护登录态 明天安排 继续完成维护登录态 ...
- LR回放https协议脚本失败: 错误 -27778: 在尝试与主机“www.baidu.com”connect 时发生 SSL 协议错误
今天用LR录制脚本协议为https协议,回放脚本时出现报错: Action.c(14): 错误 -27778: 在尝试与主机"www.baidu.com"connect 时发生 S ...
- 求解数独难题, Sudoku问题(回溯)
Introduction : 标准的数独游戏是在一个 9 X 9 的棋盘上填写 1 – 9 这 9 个数字,规则是这样的: 棋盘分成上图所示的 9 个区域(不同颜色做背景标出,每个区域是 3 X 3 ...