Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in linear time and in O(1) space.

Hint:

  1. How many majority elements could it possibly have?
  2. Do you have a better hint? Suggest it!

【题目分析】

在Majority Element中我们使用了一个巧妙的算法就是Moore's alogoirthm,在上一个题目中我们寻找的是the elements that appear more than ⌊ n/2 ⌋ times。

假设⌊ n/2 ⌋ = k,那么n最大值为2k+1,Majority Element至少为k+1个,因此Majority Element最多只能有一个。我们设置两个变量 ME 和count,ME用来存储当前的Majority Element,count对当前ME进行计数,计数规则如下。遍历数组,如果count = 0,则把当前元素赋给ME;否则的话如果当前元素=ME,则count++,否则count--;这个过程结束和,最后的EM肯定是我们Majority Element。

那么对于当前题目,设⌊ n/3 ⌋ = k,那么n最大为3k+2。如果有这样的元素它出现的个数大于k,那么这样的元素最多有两个(3k+2-2k-2 = k)。我们是否还可以用Moore's alogoirthm来解决我们的问题呢?

因为最多只能有两个Majority Element,我们设置如下几个变量:EM1,EM2,count1,count2,用来表示两个Majority Element和他们的计数。我们讨论一下下面几种情况:

1. 不存在Majority Element。那么我们最后会得到一个结果,但是这个结果可能是不正确的,需要重新遍历一次数组来对找到的元素进行计数;

2. 存在两个Majority Element。我们知道 count(EM1) >= k+1, count(EM2) >= k+1,剩余的数字 count(remain) <= k。遍历数组的过程中,如果当前元素和EM1,EM2都不相同,那么count1--,count2--,最后的结果肯定是Majority Element,因为他们的数目比其他元素多,count数不会被减到0;

3. 存在一个Majority Element。此时count(EM1) >= k+1,那么在算法执行的过程中EM1是否会被减到0呢?比如k+1个EM1出现在数组的最前面,在遍历到其他数字时,由于count(remian)<= 2k+2,因此我们担心这样的过程会导致不能找到正确的Majority Element,但事实是我们会得到正确的结果。假设最坏的情况:剩下的k+2个数字是互不相同的,如下:

[1,1,1,1,2,3,4,5]

这个数组中有8个元素,Majority Element是1,剩下的元素互不相同。在遍历前四个元素的时候count1加到4,当到达第五个元素时候,该元素不等于EM1,此时count2 = 0,因此我们会把当前元素赋值给EM2,此时count1并不发生变化。遍历到第六个元素时,当前元素与EM1和EM2都不相同。此时count1和count2才会减1。继续这个过程直到遍历完成所有的元素,我们可以看到在这个过程中,剩下的元素有一半会被赋值给EM2,而另一半元素才会使得count1--。因此count1最多减(2k+1)/2 = k次,所以如果只有一个Majority Element的话,它肯定会出现在结果中。上面只是举了最坏的情况,对于任意一种排列方式,和任意的情况这个结论都是成立的。


【java代码】

 public class Solution {
public List<Integer> majorityElement(int[] nums) {
List<Integer> list = new ArrayList<Integer>();
if(nums == null || nums.length == 0) return list; int num1 = nums[0], num2 = 0;
int count1 = 0, count2 = 0; for(int i = 0; i < nums.length; i++){
if(num1 == nums[i]) count1++;
else if(num2 == nums[i]) count2++;
else if(count1 == 0){
num1 = nums[i];
count1++;
}
else if(count2 == 0){
num2 = nums[i];
count2++;
}
else{
count1--;
count2--;
}
} count1 = 0; count2 = 0;
for(int i = 0; i < nums.length; i++){
if(nums[i] == num1) count1++;
else if(nums[i] == num2) count2++;
}
if(count1 > nums.length/3) list.add(num1);
if(count2 > nums.length/3) list.add(num2); return list;
}
}

LeetCode OJ 229. Majority Element II的更多相关文章

  1. 【LeetCode】229. Majority Element II

    Majority Element II Given an integer array of size n, find all elements that appear more than ⌊ n/3 ...

  2. 【刷题-LeetCode】229. Majority Element II

    Majority Element II Given an integer array of size n, find all elements that appear more than ⌊ n/3 ...

  3. 【LeetCode】229. Majority Element II 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 hashmap统计次数 摩尔投票法 Moore Vo ...

  4. LeetCode OJ:Majority Element II(主元素II)

    Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorit ...

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

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

  6. [LeetCode] 229. Majority Element II 多数元素 II

    Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. Note: The a ...

  7. Leetcode # 169, 229 Majority Element I and II

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

  8. 229. Majority Element II -- 找出数组中出现次数超过 ⌊ n/3 ⌋ 次的数

    Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorit ...

  9. 229. Majority Element II My Submissions Question

    Total Accepted: 23103 Total Submissions: 91679 Difficulty: Medium Given an integer array of size n, ...

随机推荐

  1. 鼠标形状css样式

    鼠标形状css样式 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  2. Openjudge-NOI题库-数根

    题目描述 Description 数根可以通过把一个数的各个位上的数字加起来得到.如果得到的数是一位数,那么这个数就是数根.如果结果是两位数或者包括更多位的数字,那么再把这些数字加起来.如此进行下去, ...

  3. 【ARM】S5PV210芯片的启动流程

    S5PV210芯片的设计者的思想 (1)芯片启动后执行iRom(BL0)的内容,进行时钟和看门狗等外设的初始化,将BL1和BL2拷贝到片内SRAM; (2)跳转到片内SRAM执行,完成外部SDRAM的 ...

  4. metasploit nessus & db_autopwn

    nessus官网:https://www.tenable.com/products/nessus-vulnerability-scanner 下载地址:https://www.tenable.com/ ...

  5. magento获取一些值的方法函数

    1显示产品列表页(列表.PHTML).echo $this->getProductListHtml(); 2.得到你的Magento的页面的路径.  echo $this->getUrl( ...

  6. Nodejs 学习

    1,Node.js REPL交互式解释器:nodejs安装完毕后,打开终端,进入到nodejs的安装目录下,输入node,进入到新的页面,该页面称为Node.js REPL (交互式解释器):可以简单 ...

  7. Uploadify 上传后的文件删除,上传队列无法更新问题

    1. 定义一个上传限制数量 var uploadLimit = 3; 2. 点击页面的删除图片成功后,将uploadLimit++操作 3. 通过uploadify的settings方式重置上传限制数 ...

  8. nodejs问题整理--fs.exists无法正确判断文件的问题

    fs.exists方法 方法说明: 测试某个路径下的文件是否存在.回调函数包含一个参数exists,true则文件存在,否则是false. 语法: fs.exists(path, callback) ...

  9. 使用SQL Server临时表来实现字符串合并处理

    处理的数据 CREATE TABLE tb(col1 varchar(10),col2 int) INSERT tb SELECT 'a',1 union ALL SELECT 'a',2 union ...

  10. C#中string.Substring 的用法

    String.SubString(int  startIndex,int length)     startIndex:截取字符串开始的位置       length:截取字符串的长度 例子:用户 输 ...