leetcode记录 169. Majority Element
2016-05-13 16:45
429 查看
最近在刷LeetCode的题的时候,发现一个特别巧妙的算法:Moore’s voting algorithm。
这个算法是解决这样一个问题:从一个数组中找出出现半数以上的元素。
Moore的主页上有这个算法的介绍:A Linear Time Majority Vote Algorithm和这个算法的一个简单示例演示:演示链接。
每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。 不难证明,如果存在元素e出现频率超过半数,那么数组中最后剩下的就只有e。
当然,最后剩下的元素也可能并没有出现半数以上。比如说数组是[1, 2, 3],最后剩下的3显然只出现了1次,并不到半数。排除这种false positive情况的方法也很简单,只要保存下原始数组,最后扫描一遍验证一下就可以了。
在算法执行过程中,我们使用常量空间实时记录一个候选元素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即为寻找的元素。上述算法的时间复杂度为O(n),而由于并不需要真的删除数组元素,我们也并不需要额外的空间来保存原始数组,空间复杂度为O(1)。
C++代码实现如下:
这个算法是解决这样一个问题:从一个数组中找出出现半数以上的元素。
Moore的主页上有这个算法的介绍:A Linear Time Majority Vote Algorithm和这个算法的一个简单示例演示:演示链接。
算法的基本思想
每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。 不难证明,如果存在元素e出现频率超过半数,那么数组中最后剩下的就只有e。当然,最后剩下的元素也可能并没有出现半数以上。比如说数组是[1, 2, 3],最后剩下的3显然只出现了1次,并不到半数。排除这种false positive情况的方法也很简单,只要保存下原始数组,最后扫描一遍验证一下就可以了。
算法的实现
在算法执行过程中,我们使用常量空间实时记录一个候选元素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即为寻找的元素。上述算法的时间复杂度为O(n),而由于并不需要真的删除数组元素,我们也并不需要额外的空间来保存原始数组,空间复杂度为O(1)。
C++代码实现如下:
<code class=" hljs cpp" style="font-family:'Source Code Pro',monospace;font-size:undefined; padding:0.5em; color:rgb(248,248,242); display:block; outline:none!important; background:rgb(35,36,31)"><span class="hljs-keyword" style="outline:none!important; color:rgb(249,38,114)">int</span> majorityElement(<span class="hljs-stl_container" style="outline:none!important"><span class="hljs-built_in" style="outline:none!important; color:rgb(230,219,116)">vector</span><<span class="hljs-keyword" style="outline:none!important; color:rgb(249,38,114)">int</span>></span> &num) { <span class="hljs-keyword" style="outline:none!important; color:rgb(249,38,114)">int</span> curIdx = <span class="hljs-number" style="outline:none!important; color:rgb(174,129,255)">0</span>, count = <span class="hljs-number" style="outline:none!important; color:rgb(174,129,255)">1</span>; <span class="hljs-keyword" style="outline:none!important; color:rgb(249,38,114)">for</span> (<span class="hljs-keyword" style="outline:none!important; color:rgb(249,38,114)">int</span> i = <span class="hljs-number" style="outline:none!important; color:rgb(174,129,255)">1</span>; i < num.size(); ++i) { num[i] == num[curIdx] ? ++count : --count; <span class="hljs-keyword" style="outline:none!important; color:rgb(249,38,114)">if</span> (!count) { curIdx = i; count = <span class="hljs-number" style="outline:none!important; color:rgb(174,129,255)">1</span>; } } <span class="hljs-keyword" style="outline:none!important; color:rgb(249,38,114)">return</span> num[curIdx]; }</code>
相关文章推荐
- ThreadLocal
- proto文件转换为oc类
- SpringMVC+easyUI实现上传图片功能小例子
- Bootstrap 中的插件的学习2(导航)
- Mockito中java.lang.noclassdeffounderror android/support/v4/app/taskstackbuilder$supportparentable
- Missing Gradle Project Information
- JavaWeb开发之深入分析请求转发和重定向的应用场景以及请求包含 (跟着龙哥学JavaWeb)
- 常用数字及模拟视频接口
- 使用AssetsLibrary库实现系统类似照片浏览器
- map 按value排序
- 深入JVM虚拟机(二) JVM运行机制
- 如何让图片在div里面剧中显示
- iOS-将经纬度转化成度分秒格式
- PHP URL 重定向 的三种方法
- ajax传递多个参数的实现代码
- Mysql开发规范
- thread pool
- Renesas+LTC6804-1的SPI通信
- HUD3488 Tour(二分图的最小权值和)
- myeclipse下SSH整合环境搭建