主元素问题 减治法

简介: 一个有n个元素的序列A中,出现次数大于n/2的元素称为主元素。现给定一个序列(保证存在主元素),求其主元素。 一种思路是Boyer和Moore提出的减治法,可以在线性时间内求得主元素。如果不确定序列是否存在主元素,还需要再加一个线性的判断。

一个有n个元素的序列A中,出现次数大于n/2的元素称为主元素。现给定一个序列(保证存在主元素),求其主元素

一种思路是Boyer和Moore提出的减治法,可以在线性时间内求得主元素。如果不确定序列是否存在主元素,还需要再加一个线性的判断。

以下假设A的主元素存在,且出现了k次,则其他元素出现的次数为n - k,二者的差记为c = 2k-n。可知x为主元素当且仅当 c > 0。

考查序列A的长度为2m的前缀P,若其中某个元素 x 出现的次数达到m,则此时可减而治之,分析如下,参考了数据结构课本的“众数选取”部分:

  1. 若 x 确实为A的主元素,则A剪去前缀P后得到的后缀S,x的个数与非主元素的个数都减少了m,但二者的差仍为c,所以后缀S的主元素必然也是x。

  2. 若A的主元素不是 x,而是另一个元素y,那么剪去P后,至少除去了m个非主元素,所以后缀S中的c不会减小,S的主元素仍为y。

实现上,我们维护一个“差额计数器c” 和一个当前候选值maj ,初始化maj=A[0], c = 1。

从左到右扫描序列A,若A[i]==maj则c++,否则c--。当c减到0时,说明maj在当前的长度为2m的区间内恰好出现了m次,根据上面的分析,此时可以放心地剪去当前区间,只考虑后缀;所以我们置新的maj = A[i], c = 1,继续扫描至结尾,最终maj的值就是最后一个后缀的主元素。

若不确定原序列A是否存在主元素,可以扫描一遍统计下maj的个数。

题目嘛,找到了这么一道:https://leetcode.com/problems/majority-element/

参考了 http://blog.csdn.net/baimafujinji/article/details/50478012

 1 int majorityElement(vector<int>& nums) {
 2     int major;
 3     for(int c=0, i=0; i < nums.size(); i++){
 4         if(c == 0){
 5             major = nums[i];
 6             c = 1;
 7         }else
 8             major == nums[i] ? c++ : c--;
 9     }
10     return major;
11 }

 

目录
相关文章
|
3月前
|
存储 算法 C++
高精度算法(加、减、乘、除,使用c++实现)
高精度算法(加、减、乘、除,使用c++实现)
979 0
高精度算法(加、减、乘、除,使用c++实现)
|
8月前
|
存储 C语言
用加法器实现补码的加/减运算
用加法器实现补码的加/减运算
214 0
小于等于K的最大子数组累加和
小于等于K的最大子数组累加和
|
机器学习/深度学习 存储 算法
高精度算法(加,减,乘,除)
为啥要高精度算法,如果有一个数很大比如10的100次方,很明显计算机不能存储这么大的数。那么我们可以采用高精度算法。利用数组和字符串来计算。
|
C语言 Python
左移(<<),右移(>>), (i++ 如果没有接收方,那么“先使用”,如何理解?),取余和取模一样吗?
左移(<<),右移(>>), (i++ 如果没有接收方,那么“先使用”,如何理解?),取余和取模一样吗?
|
Java C++ Python
负数取余,取余和取模
负数取余,取余和取模
2.2.4加减运算和溢出判断
2.2.4加减运算和溢出判断
|
缓存 算法 网络协议
减治法
分治法是把一个大问题划分为若干个子问题,分别求解各个子问题,然后再把子问题的解进行合并得到原问题的解。 减治法同样是把一个大问题划分为若干个子问题,但是这些子问题不需要分别求解,只需求解其中的一个子问题,因而也无需对子问题的解进行合并。
大数的四则运算(加,减,乘,除)处理
大数的四则运算(加,减,乘,除)处理
642 0
大数的四则运算(加,减,乘,除)处理
|
存储 Oracle 关系型数据库