主元素问题 减治法

一个有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 }
时间: 2024-08-10 21:21:09

主元素问题 减治法的相关文章

主元素 算法

问题描述: 设T[0:n-1]是n个元素的数组.对任一元素x,设S(x)={i|T[i]=x}.当|S(x)|>n/2时,称x为T的主元素.设计一个线性时间算法,确定T[0:n-1]是否有一个主元素. 分析与解答: (1)基于分治法的线性期望时间求主元素算法 中位数:数列排序后位于最中间的那个数,如果一个数列有主元素,那么必然是中位数.求一个数列有没有主元素,只要看中位数是不是主元素. 找中位数的方法:选择一个元素作为划分起点,然后用快速排序的方法将小于它的移动到左边,大于它的移动到右边.这样将

求数组主元素的递归算法

数组A是具有n个元素的数组,x是A中的一个元素,若A中有一半以上的元素与A相同,则称x是数组A的主元素.例如 ,数组A={1,3,2,3,3,4,3},元素3就是该数组的主元素. 1.移去数组中的两个不同元素后,如果原来数组中有主元素,那么该主元素依然是新数组的主元素. 2.如果数组2k个元素中有k个元素相同(k<n/2),移去这2k个元素以后,如果原来数组中有主元素,那么该主元素依然是新数组的主元素. 如果新数组只剩下一个元素,该元素可作为主元素的候选者.新数组是若干个相同元素,该元素可作为主

线性时间内确定T[0:n]是否有一个主元素

设T[0:n-1]是n 个元素的数组.对任一元素x,设S(x)={ i | T[i]=x}.当| S(x) |>n/2 时,称x 为T 的主元素.设计一个算法,确定T[0:n-1]是否有一个主元素. 算法描述如下: a1 a2 a3 a4 … aj aj+1 … … an 首先取a1 存入m 中,计数器k 置为1. 然后让m 比较a1,a2…,如果与m 相同,则k 加1,如果不同,k 要减1. 这样执行下去, 可能会在比较完aj 时,k=0,这时从新取aj+1 存入m,k 置为1. 重复上述操作

寻找主元素

主元素这个问题,有个nlogn的算法,但是还有比它更快的,有O(n)的算法,基本思想是,从头到尾遍历,先将第一个元素保存到一个变量中,然后依次往后遍历,每遍历到与它的值相同的元素时,就要将它的个数+1, 不同时-1, 这样是因为如果存在主元素,那么主元素的个数一定是大于n/2的,所以最后这样抵消下来剩下的一定是主元素,如果判断它不存在呢,就需要再遍历一遍,看最后找到的这个是不是主元素,其中有个细节就是当那个保存的个数减到0的时候怎么办,如果减到零,就让它等于当前遍历到的这个元素,代码如下, 1

主元素 II

主元素 II 给定一个整型数组,找到主元素,它在数组中的出现次数严格大于数组元素个数的三分之一. 样例 给出数组[1,2,1,2,1,3,3] 返回 1 注意 数组中只有唯一的主元素 挑战 要求时间复杂度为O(n),空间复杂度为O(1). 嗯.. 百度了一下. 主元素可能有两个,于是设置两个当前主元素.遍历nums,如果和某个当前住元素相等,则计数加一.如果都不相等 计数减一,若减后计数小于等于0,则将对应的当前住元素更换. 最后需要验证,应为当前主元素只有一个,候选有两个. lintcode上

减治法

核心数学式: f(n) = f(n-1) + F; 应用:插入排序:生成排序/子集 f(n) = f(n/2) + F;      应用:假币问题:俄式乘法 f(n) = f(n-k) + F; 应用:查找第k大/小的元素 实现思路:考虑对于元素数量为n的集合的执行结果,如何用数量为n-1.n/2或者n-k的集合的执行结果来表示 实现方法:迭代和递归都可以 /* * 减治法 * 主要思路: * 基于减治法f(n) = f(n-1)...的思路,可以想象, * 对于长度为n的序列,它的所有子集,是

九章算法面试题37 主元素

九章算法官网-原文网址 http://www.jiuzhang.com/problem/37/ 题目 主元素(Majority Number)定义为数组中出现次数严格超过一半的数.找到这个数.要求使用O(1)的额外空间和O(n)的时间. 进阶1:如果数组中存在且只存在一个出现次数严格超过1/3的数,找到这个数.要求使用O(1)的额外空间和O(n)的时间. 进阶2:如果数组中存在且只存在一个出现次数严格超过1/k的数,找到这个数.要求使用O(k)的额外空间和O(n)的时间 解答 采用抵消法.一旦发

求一个序列中的主元素

问题(2013 统考408真题):已知一个整数序列A = (a0,a1,...,an-1), 其中0≤ai≤n (0≤i<n).若存在ap1=ap2...=apm=x且m>n/2 (0≤pk≤n,1≤k≤m),则称x为A的主元素.例如,A=(0,5,5,3,5,7,5,5),则5为主元素,又如A=(0, 5, 5,3, 5, 1, 5,7),则A中没有主元素.假设A中的n个元素保存在一个一维数组中, 请设计一个尽可能高效的算法,找出A的主元素.若存在主元素,则输出该元素:否则输出-1. 解答:

[容易]主元素

题目来源:http://www.lintcode.com/zh-cn/problem/majority-number/ 这道题注意题意,给出的数组一定是存在这个主元素的,不能给一个没有主元素的数组测试. 方法1:穷举法 使用两个for循环计算出每个元素出现的次数, 如果该元素出现次数大于数组元素的二分之一立即返回该元素. 可以accept的程序如下: 1 class Solution { 2 public: 3 /** 4 * @param nums: A list of integers 5