目录

1.引入

2.摩尔投票算法

3.基本步骤

摩尔投票法分为两个阶段:

1.抵消阶段

2.检验阶段

4.代码实现

5.扩展沿伸

6.总结


1.引入

我们来看一个问题:

假设有一个无序数组长度为n,要求找出其中出现次数超过n/2的数,要求时间复杂度为O(n),空间复杂度为O(1).


第一种方法就是遍历数组的每一个元素,统计出现的次数,但时间复杂度显然不符合要求。第二种方法是排序,我们可以先对数组进行排序,然后判断中间的数是否满足条件,这种做法时间复杂度最低为O(nlogn)。

第三种做法是用哈希表记录元素出现的次数,然后遍历哈希表寻找满足条件的元素,此时时间复杂度为O(n),空间复杂度为O(n)。


显然以上三种做法都不能同时符合题目空间复杂度和时间复杂度的要求,下面我们将介绍一种主要解决多数元素的一种算法---摩尔投票算法

2.摩尔投票算法

摩尔投票法又称多数投票法,主要用于解决一个数组中的众数(要求数量超过数组长度的二分之一)的问题。它的原理如下:

我们将数组的元素想象成一张张选票,数字代表候选人的序号,每次从数组中取两个元素,如果两个元素相同,则选票数进行累加;如果不相同,则选票进行抵消,直到遍历完整个数组。如果数组中存在符合要求的候选人,则最后剩下的选票一定是最终候选人的序号。(极限一换一规则)

3.基本步骤

摩尔投票法分为两个阶段:

1.抵消阶段

本阶段将数组的元素(候选人)进行抵消。我们先定义候选人major为第一个元素,然后设置计数器count为1,向后进行遍历,当后续元素和major相等,则count++,否则count--。如果count为0时,就将候选人major改为下一个元素,count置1,以此循环直到数组遍历完毕。如果数组中存在出现次数大于n/2的元素,则最后major一定是这个元素。动图如下:

2.检验阶段

由于我们不知道数组是否存在符合条件的多数元素,所以需要对最后的major进行检验。例如数组为【1,2,3】,最后求出的major为3,但3显然不是数组的多数元素。所以还需遍历一遍数组判断major出现次数是否大于n/2。


4.代码实现

回到我们文章开头的题目,这道题出处为LeetCode第169题,代码如下:

int majorityElement(int* nums, int numsSize)
{//抵消阶段int count = 1;int major = nums[0];for (int i = 1; i < numsSize; i++){if (count != 0){if (nums[i] == major){count++;}else{count--;}}else{major = nums[i];count = 1;}}//检验阶段int n = 0;for (int i = 0; i < numsSize; i++){if (major == nums[i]){n++;}}if (n > numsSize / 2){return major;}else{return -1;}
}

5.扩展沿伸

我们先来看题目,本题是LeetCode第229题,是多数元素的改编题:

本题的本质还是求众数,通过题目我们可以得知,出现次数超过n/3次的元素至多只有两个。因此我们可以将摩尔投票法进行扩展,步骤如下:

1.定义两个候选人,用major1和major2两个变量维护,然后设置两个计数器count1和count2,向后遍历数组。

2.当和major1或major2相等时,将count1或count2加1,当不等于major1和major2时将count1和count2都减1,也就是三者抵消。当count1或count2为0时则将major1或major2改为下一个候选人(数组元素)。

3.当遍历完数组后,再对major1和major2进行检验,即可求出答案。

代码如下:

int* majorityElement(int* nums, int numsSize, int* returnSize)
{if (nums == NULL || numsSize <= 1)    //数组为空或最多只有一个元素{*returnSize = numsSize;return nums;}//抵消阶段int major1 = nums[0];   //候选人1int major2 = nums[1];   //候选人2int count1 = 0;         //票数int count2 = 0;         //票数for (int i = 0; i < numsSize; i++){if (nums[i] == major1){count1++;}else if (nums[i] == major2){count2++;}else if (count1 == 0){major1 = nums[i];count1 = 1;}else if (count2 == 0){major2 = nums[i];count2 = 1;}else{count1--;count2--;}}//检验阶段int n1 = 0, n2 = 0;*returnSize = 0;int* ret = (int*)malloc(2 * sizeof(int));for (int i = 0; i < numsSize; i++){if (nums[i] == major1){n1++;}else if (nums[i] == major2){n2++;}}if (n1 > numsSize / 3)      //major1符合要求{ret[*returnSize] = major1;(*returnSize)++;        }if (n2 > numsSize / 3)     //major2符合要求{ret[*returnSize] = major2;(*returnSize)++;}return ret;
}

6.总结

通过以上两道题目,我们了解了摩尔投票算法适用于寻找一个数组中出现次数超过一定比例的元素。

当题目要找出出现次数超过1/2的元素,则至多有1个元素满足

当题目要找出出现次数超过1/3的元素,则至多有2个元素满足

当题目要找出出现次数超过1/4的元素,则至多有3个元素满足

当题目要找出出现次数超过1/n的元素,则至多有n-1个元素(n>=2)满足


至多有n个元素满足,我们就用n个变量和n个计数器来维护这n个元素。当数组遍历完后,还需再次检验这n个元素是否满足题目要求。


以上,就是本期全部内容。

制作不易,能否点个赞再走呢qwq

C语言刷题之摩尔投票法相关推荐

  1. [剑指offer][JAVA]面试题第[39]题[数组中出现次数超过一半的数字][HashMap][摩尔投票法]

    [问题描述][简单] 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.你可以假设数组是非空的,并且给定的数组总是存在多数元素.示例 1:输入: [1, 2, 3, 2, 2, 2, 5, ...

  2. 动态规划和摩尔投票法

    动态规划 维基百科对动态规划(Dynamic programming,简称DP)的定义是一种在数学.管理科学.计算机科学.经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问 ...

  3. 摩尔投票法(Boyer–Moore majority vote algorithm)

    参考资料 论文MJRTY A Fast Majority Vote Algorithm 算法演示网站 维基百科 算法解读 概述 摩尔投票法(Boyer–Moore majority vote algo ...

  4. 小小算法,可笑可笑——摩尔投票法(集万家之长)

    摩尔投票法 不多说,先上题目. 问题描述:leetcode 229题 给定一个大小为 n 的整数数组,找出其中的所有的出现超过 ⌊ n/3 ⌋ 次的元素. 这还不简单!直接暴力计数,上map,easy ...

  5. 摩尔投票法(力扣- -229. 求众数 II)

    摩尔投票法(力扣- -229. 求众数 II) 文章目录 摩尔投票法(力扣- -229. 求众数 II) 一.题目描述 二.分析 摩尔投票法 总结 三.代码 一.题目描述 二.分析 这道题如果用O(N ...

  6. 【LeetCode笔记】169. 多数元素(Java、摩尔投票法、哈希表)

    文章目录 题目描述 思路 & 代码 思路一:哈希表 思路二: 摩尔投票法 题目描述 好家伙,这是今天最有意思的题目了 思路 & 代码 思路一:哈希表 先说缺点:空间复杂度O(n) 一次 ...

  7. c语言刷题(牛客网)

    c语言刷题(牛客网100道基础题) 学习没有捷径,唯有重复多练,这是浩克为大家找的牛客网刷题资源,如果你正在学或者学完了都可以来检验一下自己能力. 浩克也会专门开个专栏来讲解c语言刷题,让大家对c语言 ...

  8. 2020年 Moore majority vote algorithm 摩尔投票法知多少

    第一眼看到这个题目,想到的是使用Map来统计出现频次,然后遍历找出频次大于n/2的元素. class Solution {public int majorityElement(int[] nums) ...

  9. 关于C语言刷题(#define宏定义函数的常见错误)

    关于C语言刷题(#define宏定义函数的常见错误) 首先我们来先看对#define的定义 define,宏定义,C语言中预处理命令一种.分为无参宏定义和带参宏定义.无参宏定义的一般形式为:#defi ...

最新文章

  1. c++中的vector的常见使用
  2. 调试Tomcat源码
  3. ppt 简单动画制作
  4. 病案编码员需要计算机的什么知识,前辈分享:优秀编码员必须经历的成长过程,你到哪一级了?...
  5. 茅塞顿开:Spring Aware原理解析
  6. php单机session消失_Session 失效的原因汇总及解决丢失办法
  7. pacman吃豆人_通过Tensorflow和强化学习实现自动化吃豆人PacMan
  8. github客户端进行token认证
  9. 如何免费下载百度文库、豆丁网等网站的文档
  10. Brocade博科光纤交换机之 常用命令
  11. 你的PCB地线走的对吗?为什么要有主地?
  12. 百度脑图制作的简单的个人介绍
  13. 同条网线电脑正常上网,手机连接wifi成功,但是无法访问互联网
  14. 计算机一级c云大,云南大学网红C位易主!新晋流量霸主竟然是……
  15. Jenkins maven自动发布配置
  16. 阅读笔记 - 20220401
  17. node 工具模块lodash
  18. 支付宝被罚18万元;金立副总裁回应60亿广告费;苹果再遭专利诉讼丨价值早报
  19. 高中信息技术html语言,高中信息技术《Python语言》模块试卷
  20. mt6592android7,MT6592/MT6592M/MT6592T三版本性能对比

热门文章

  1. Mac M1 彻底卸载 mysql
  2. Git stash命令详解和使用
  3. 服务器怎么查看系统密钥,如何查找Power BI本地报表服务器产品密钥
  4. phpStudy里面的MySQL启动不了,本地之前安装过MySQL
  5. Vue数据代理的原理
  6. ClickOnce 不支持请求执行级别“requireAdministrator”
  7. 卷积神经网络的图像分割,一维cnn卷积神经网络
  8. python库——pprint
  9. Flyme支付安全保护,年前来一发~
  10. python 的数组排序问题