博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Boyer-Moore 算法
阅读量:7081 次
发布时间:2019-06-28

本文共 1691 字,大约阅读时间需要 5 分钟。

问题定义

给定一个长度为 n的数组:

int[] nums

其中有一个数,它出现的次数大于n/2,称为主要元素,找到它。

看起来不算是个难题,但好玩。

这是一个投票问题,可以模拟我们在投票表决时的计票过程。用一个hash table或者dictionary,数组中的数作为key,它们出现的次数为value。本文想讨论的是下边这些算法。

1. 常见解法

1.1 排序

结论很简单:排序完之后,主要元素必然在下标n/2的位置。看下面两个例子就很清楚了:

nums:    1,  1,  1,  2,  2  i      0   1   2   3   4n/2=5/2=2nums[2]=1主要元素是最小的数,排序后集中在最左边
nums:    1,  1,  2,  2,  2  i      0   1   2   3   4n/2=5/2=2nums[2]=2主要元素是最大的数,排序后集中在最右边

如果主要元素既不是最大的也不是最小的,那主要元素集中在中间一段,包括n/2。Python一句搞定:

def majorityElement(self, nums):        return sorted(nums)[len(nums)/2]

分析:元素是int型,没有限制更小的范围,基于比较的排序算法,最快O(nlogn)。

1.2 位操作

这里设int为32位整数。我们对这些数以二进制的形式,逐位观察,尝试构造出主要元素来。对32位中的每一位,如果1占多数,则主要元素的对应位为1,否则为0。

nums:  1,  2,  3,  3,  3Binary:  1:   0b0000....0001  2:   0b0000....0010  3:   0b0000....0011  3:   0b0000....0011  3:   0b0000....0011major: 0b0000....0011

Java实现:

public int majorityElement(int[] nums) {      int res=0,major=nums.length/2;      for (int i=31;i>=0;i--){          int pos=0;          for(int n:nums)              pos+=(n>>i)&1;          pos=pos>major? 1:0;          res|=pos<

分析:时间复杂度为O(n),带个系数32,实际工作起来还是很快的。

2. Boyer-Moore 算法

提出Boyer-Moore 算法的。

基本思想:

比较直观的解释:在数组中找到两个不相同的元素并删除它们,不断重复此过程,直到数组中元素都相同,那么剩下的元素就是主要元素。

思想并不复杂,但是要凭空想出这个算法来也不是件容易的事。另外,给我们的是数组,直接在里面删除元素是很费时的。取而代之,可以利用一个计数变量来实现。

def majorityElement(self, nums):    count,major=0,0    for n in nums:        if count==0:            major=n        if major==n:            count+=1        else:            count-=1    return major

对于上面的代码:

  1. 先随意确定一个候选元素,count是候选元素的计数,当遇到一个跟候选元素不同的元素时,两者数量上抵消一个,count减1。一旦count变成0,就重新找一个候选元素。

  2. 当遇到一个与候选元素不同的元素时,就要抵消。对于候选元素和当前元素,可能存在两种情况:

    A. 两者中有一个正好是主要元素

B. 两者都不是主要元素

对于情况 A,抵消过后,主要元素还是主要元素;对于情况 B,可以说主要的元素的地位得到了巩固。所以算法最终能找到主要元素。

转载地址:http://ipvml.baihongyu.com/

你可能感兴趣的文章
HTML逆向解析生成Markdown
查看>>
架构师都知道的分布式对象存储解决方案
查看>>
[译] 提高编程能力的秘诀
查看>>
Java&Spring系列笔记
查看>>
理解JS中的this
查看>>
一位6年老Android面经总结
查看>>
DDD基础知识1
查看>>
前端WEB-API 第四天-- 操作DOM 与 动态创建 DOM
查看>>
notify,notifyAll区别(生产者消费者案例)
查看>>
Spring IoC、AOP、Transaction、MVC 归纳小结
查看>>
Linux常用命令 —locate、which、whereis、grep
查看>>
编译FFMpeg
查看>>
css-margin
查看>>
深入理解Javascript中的隐式调用
查看>>
kotlin学习笔记——lambda表达式
查看>>
ES6-Promise 源码阅读
查看>>
Java系列3---注解
查看>>
正则表达式
查看>>
小猿圈python学习-字符编码的转换
查看>>
【Android自定义View】绘图之Canvas篇(五)
查看>>