目录

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. debian10 简单的bash脚本监控apache运行状态
  2. 面试命中率90%的点 —— MySQL锁
  3. 王者荣耀活动精选 Blink 第二弹来袭!
  4. 【学术相关】数学公式如何用Markdown优雅地写出来
  5. php mysql 分组 分页_简单的PHP+Mysql实现分页
  6. 集合(Collection和Map)
  7. grid - 隐式命名网格线名称
  8. 史无前例! 中国学者一天发6篇Nature,在多领域取得重大进展
  9. 数据装载全/存量直接装载到目标表_09
  10. 【Html】Html基本标记
  11. 易到高管被原百度外卖CEO巩振兵逼下跪:职场人到中年的无奈
  12. 1.VUE 安装以及vue.js下的第一个hello world
  13. win10c语言乱码修复方法,“字体库异常、电脑乱码的解决方案”的解决方案
  14. SM4算法 C语言 (从OpenSSL库中分离算法:七)
  15. 冷高轮时间王思聪吃热狗windows电脑壁纸下载
  16. 苹果系统摩尔庄园是什么服务器,摩尔庄园手游官服和渠道服有什么区别_可以一起玩吗_官服和渠道服详细介绍...
  17. docker(9):高级网络配置
  18. Mindspore | lenet 模型代码
  19. tenacity库 重试代码
  20. ggplot2读书笔记9:第六章 标度(二)

热门文章

  1. 世界上最远的距离zz
  2. java放在c盘x86_你开发的软件安装在C盘Program Files (x86)下产生的异常
  3. SecureCRT 使用python脚本
  4. CPU镜头和非CPU镜头
  5. 169_技巧_Power BI 依据促销日历计算销售金额
  6. Oracle数据库所有知识点集合
  7. Java获取时间时间格式化最全总结
  8. 紧急电话有线广播与调频广播解决方案
  9. 关于python安装库的方法
  10. 纯前端表格控件SpreadJS新手入门指南 - 复制粘贴