摩尔投票算法(Moore‘s Voting Algorithm)及例题

摩尔投票算法(Moore's Voting Algorithm)及例题

    • 摩尔投票算法简介
    • 摩尔投票算法算法思想
    • 摩尔投票算法经典题目
      • 169. 多数元素
      • 229. 多数元素 II
      • 6927. 合法分割的最小下标

上午打力扣第 354 场周赛最后十五分钟用摩尔投票算法直接秒了第三题。

摩尔投票算法简介

摩尔投票算法最早由 Robert S. Boyer 和 J Strother Moore 在 1981 年的论文 “MJRTY—A Fast Majority Vote Algorithm” 中提出。这篇论文描述了摩尔投票算法的原理和证明,并展示了它在实际应用中的高效性。

论文的引用信息如下:

Title: MJRTY—A Fast Majority Vote Algorithm

Authors: Robert S. Boyer, J Strother Moore

Year: 1981 Published in: Automated

Reasoning: Essays in Honor of Woody Bledsoe

Publisher: Springer-Verlag

Pages: 105-117

具体算法证明大家可以去查看相关论文

摩尔投票算法算法思想

摩尔投票算法(Moore’s Voting Algorithm)是一种用于在数组中寻找多数元素的有效方法。所谓多数元素,是指在数组中出现次数超过一半以上的元素。最经典的例子就是用于众数的寻找。

摩尔投票算法的基本思想很简单,它通过消除不同元素之间的对抗来找到可能的多数元素。算法遍历数组并维护两个变量:候选元素和其对应的票数。开始时,候选元素为空,票数为0。然后对于数组中的每个元素,执行以下步骤:

  1. 如果票数为0,将当前元素设为候选元素,并将票数设置为1。
  2. 如果当前元素等于候选元素,则票数加1。
  3. 如果当前元素不等于候选元素,则票数减1。

这样做的效果是,相同元素的票数会相互抵消,不同元素的对抗也会导致票数减少。由于多数元素的出现次数超过一半以上,所以最终留下的候选元素就很有可能是多数元素。

遍历完整个数组后,候选元素即为多数元素的候选者。然后我们需要进一步验证候选元素是否真的是多数元素,因为可能存在没有多数元素的情况。我们再次遍历数组,统计候选元素的出现次数,如果发现它的出现次数超过了一半以上,则确认它为多数元素;否则,表示没有多数元素。

以下是摩尔投票算法的伪代码:

function findMajorityElement(nums):candidate = Nonecount = 0for num in nums:if count == 0:candidate = numif candidate == num:count += 1else:count -= 1# 进行第二次遍历,验证 candidate 是否为多数元素count = 0for num in nums:if num == candidate:count += 1if count > len(nums) / 2:return candidateelse:return None

摩尔投票算法的时间复杂度为O(n),空间复杂度为O(1),是一种高效的寻找多数元素的算法。

摩尔投票算法经典题目

169. 多数元素

169. 多数元素

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

image-20230716151822817

解题思路:

直接摩尔投票算法秒了

class Solution {
public:int majorityElement(vector<int>& nums) {int candidate, count = 0;for(auto num : nums) {if(count == 0) candidate = num;if(num == candidate) count++;else count--;}return candidate;}
};

229. 多数元素 II

229. 多数元素 II

给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。

image-20230716162130453

解题思路:

与上面那道题不同的是,这道题可能会出现两个不同的多数元素,可以这样设想,这次需要投票选举出一位或者两位候选人,而每位候选人的票数只要大于总人数的三分之一即可。

基于摩尔投票算法的核心思想,这道题可以这么写:

  • 我们每次检测当前元素是否为第一个选中的元素或者第二个选中的元素。

  • 每次我们发现当前元素与已经选中的两个元素都不相同,则将两个候选元素都进行抵消一次,因为当三个元素互不相同时会被抵消,最终只剩下1个元素。

  • 如果存在最终选票大于 0 的元素,我们还需要再次统计已选中元素的次数,检查元素的次数是否大于$ \lfloor\frac{n}{3}\rfloor $。

class Solution {
public:static const int inf = INT_MAX;vector<int> majorityElement(vector<int>& nums) {vector<int>ans;int candidate1 = 0, count1 = 0, candidate2 = inf, count2 = 0;for(auto num : nums) {  // 第一次遍历,寻找两个候选元素if(count1 == 0 && num != candidate2) candidate1 = num; // 设置第一个候选元素else if(count2 == 0 && num != candidate1) candidate2 = num; // 设置第二个候选元素if(num == candidate1) count1++; // 如果当前元素等于候选元素1,票数加1else if(num == candidate2) count2++; // 如果当前元素等于候选元素2,票数加1else { // 与候选元素1、2对抗,票数减1count1--;count2--;}}int sum1 = 0, sum2 = 0;for(auto i : nums) { // 第二次遍历,统计两个候选元素的出现次数if(candidate1 == i) sum1++;if(candidate2 == i) sum2++;}if(sum1 > nums.size() / 3) ans.push_back(candidate1);if(sum2 > nums.size() / 3) ans.push_back(candidate2);return ans;}
};

6927. 合法分割的最小下标

6927. 合法分割的最小下标

如果元素 x 在长度为 m 的整数数组 arr 中满足 f r e q ( x ) ∗ 2 > m freq(x) * 2 > m freq(x)2>m ,那么我们称 x 是 支配元素 。其中 f r e q ( x ) freq(x) freq(x) x x x 在数组 arr 中出现的次数。注意,根据这个定义,数组 arr 最多 只会有 一个 支配元素。

给你一个下标从 0 开始长度为 n 的整数数组 nums ,数据保证它含有一个支配元素。

你需要在下标 i 处将 nums 分割成两个数组 nums[0, …, i] 和 nums[i + 1, …, n - 1] ,如果一个分割满足以下条件,我们称它是 合法 的:

  • 0 <= i < n - 1
  • nums[0, …, i] 和 nums[i + 1, …, n - 1] 的支配元素相同。

这里, nums[i, …, j] 表示 nums 的一个子数组,它开始于下标 i ,结束于下标 j ,两个端点都包含在子数组内。特别地,如果 j < i ,那么 nums[i, …, j] 表示一个空数组。

请你返回一个 合法分割 的 最小 下标。如果合法分割不存在,返回 -1 。

image-20230716164409930

解题思路:

摩尔投票算法求解出整个数组的支配元素,然后遍历数组,找到下标i,使得从该下标分割数组让两个子数组的合法。

class Solution {
public:int minimumIndex(vector<int>& nums) {// 找到支配元素int count = 0, sum = 0;int candidate = 0;for (auto num : nums) {if (count == 0) candidate = num;count += (num == candidate) ? 1 : -1;}for(auto i : nums) if(i == candidate) sum++;// cout << candidate << endl;// 遍历找到分割点int leftcount = 0, rightcount = 0;for(int i = 0; i < nums.size(); i++) {if(nums[i] == candidate) {leftcount++;rightcount = sum - leftcount;if(leftcount * 2 > i + 1 && rightcount * 2 > nums.size() - i - 1) {// cout << leftcount << " " << rightcount << endl;return i;}}}return -1;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1120.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【图像处理】基于双目视觉的物体体积测量算法研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【QT/OpenCV】QT实现张正友相机标定

相机标定 01、相机标定02、OpenCV函数及其张正友标定法2.1、相机标定步骤2.2、相机标定相关函数2.2.1 提取角点--- findChessboardCorners2.2.2 亚像素角点提取1--- find4QuadCornerSubpix2.2.3 亚像素角点提取2--- cornerSubPix2.2.4 绘制内角点 --- drawChessboardCorners2.2…

生成式AI:大语言模型ChatGPT交互的机制

推荐&#xff1a;将NSDT场景编辑器加入你的3D工具链 3D工具集&#xff1a;NSDT简石数字孪生 与 ChatGPT 有效交互的快速工程 随着生成式人工智能的普及&#xff0c;特别是 ChatGPT&#xff0c;提示已成为人工智能世界中越来越重要的技能。制作提示&#xff0c;与大型语言模型&…

【C语言督学营 第十八天】考研408排序大题初探(将排序思想融入题目)

文章目录 题目一分析代码实战 题目二分析代码实战 补充(快排与归并)数据结构大题注意点&#xff01;&#xff01;&#xff01;(评分标准) 题目一 分析 (1&#xff09;算法的基本设计思想 由题意知&#xff0c;将最小的nl2个元素放在Ai中&#xff0c;其余的元素放在A2中&#x…

Linux信号

文章目录 一.信号基础二.信号的产生1.使用键盘组合键发送信号&#xff08;只能给当前正在运行的进程发&#xff09;信号捕捉2.使用kill指令&#xff08;可以向任意进程发送信号&#xff09;3.使用raise&#xff08;&#xff09;让进程自己给自己发送信号4.硬件异常产生信号a.除…

Java中List的使用方法简单介绍

Java中List的使用方法简单介绍 java中的List就是一种集合对象&#xff0c;将所有的对象集中到一起存储。List里面可以放任意的java对象&#xff0c;也可以直接放值。 使用方法很简单&#xff0c;类似于数组。 使用List之前必须在程序头引入java.util.* import java.util.*; pub…

分享四款导航页 个人主页html源码

一、开源免费&#xff0c;可以展示很多社交账号&#xff0c;也可以更换社交账号图标指向你的网站&#xff0c;上传后即可使用 https://wwwf.lanzout.com/ik7R912s031g 二、开源免费&#xff0c;不过部署稍微麻烦点 https://wwwf.lanzout.com/iCq2u12s02wb 三、适合做成导航页面…

golang网络编程学习-1rpc

网络编程主要的内容是&#xff1a; 1.TCP网络编程 2.http服务 3.rpc服务 4.websocket服务 一、rpc RPC 框架----- 远程过程调用协议RPC&#xff08;Remote Procedure Call Protocol)-----允许像调用本地服务一样调用远程服务。 RPC是指远程过程调用&#xff0c;也就是说两台服…

MySQL结构以及数据管理(增删改查)

目录 1.数据库的简介 2.数据库分类 2.1关系型数据库 2.2 非关系型数据库 3.mysql的数据类型 3.1 常用的数据库类型 4.mysql的数据库结构 4.1 查看库信息 4.2 查看表信息 5.SQL 语句 5.1 SQL语言分类&#xff1a; 1.数据库的简介 数据库&#xff08;database&#…

Spark高级特性

spark shuffle 中 map 和 reduce 是一个相对的概念&#xff0c;map是产生一批数据&#xff0c;reduce是接收一批数据&#xff0c;前一个任务是map&#xff0c;后一个任务是reduce。 hashShuffle&#xff1a;hash分组&#xff0c;一个task里面按hash值的不同&#xff0c;分到不…

微服务优雅上下线的实践方法

导语 本文介绍了微服务优雅上下线的实践方法及原理&#xff0c;包括适用于 Spring 应用的优雅上下线逻辑和服务预热&#xff0c;以及使用 Docker 实现无损下线的 Demo。同时&#xff0c;本文还总结了优雅上下线的价值和挑战。 作者简介 颜松柏 腾讯云微服务架构师 拥有超过…

Flask_实现token鉴权

目录 1、安装依赖 2、实现代码 3、测试 源码等资料获取方法 1、安装依赖 pip install flask pip install pycryptodome 2、实现代码 import random import string import time import base64from functools import wrapsfrom flask import Flask, jsonify, session, req…

RabbitMQ如何保证消息的可靠性6000字详解

RabbitMQ通过生产者、消费者以及MQ Broker达到了解耦的特点&#xff0c;实现了异步通讯等一些优点&#xff0c;但是在消息的传递中引入了MQ Broker必然会带来一些其他问题&#xff0c;比如如何保证消息在传输过程中可靠性&#xff08;即不让数据丢失&#xff0c;发送一次消息就…

学习babylon.js --- [2] 项目工程搭建

本文讲述如何搭建babylonjs的项目工程。 一 准备 首先创建一个目录叫MyProject&#xff0c;然后在这个目录里再创建三个目录&#xff1a;dist&#xff0c;public和src&#xff0c;如下&#xff0c; 接着在src目录里添加一个文件叫app.ts&#xff0c;本文使用typescript&#…

docker数据卷权限管理--理论和验证

一、Docker容器中用户权限管理 Linux系统的权限管理是由uid和gid负责&#xff0c;Linux系统会检查创建进程的uid和gid&#xff0c;以确定它是否有足够的权限修改文件&#xff0c;而非是通过用户名和用户组来确认。 同样&#xff0c;在docker容器中主机上运行的所有容器共享同一…

【kubernetes系列】Kubernetes之配置dashboard安装使用

Kubernetes之配置dashboard 概述 Dashboard 是基于网页的 Kubernetes 用户界面。 你可以使用 Dashboard 将容器应用部署到 Kubernetes 集群中&#xff0c;也可以对容器应用排错&#xff0c;还能管理集群资源。 你可以使用 Dashboard 获取运行在集群中的应用的概览信息&#x…

【单例模式】—— 每天一点小知识

&#x1f4a7; 单例模式 \color{#FF1493}{单例模式} 单例模式&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风撞见云的博客&#x1f390; &#x1f433; 《数据结构与算法》专栏的文章图文并茂&#x1f995;生动形…

LiveGBS流媒体平台GB/T28181功能-作为上级平台对接海康大华华为宇视等下级平台监控摄像机NVR硬件执法仪等GB28181设备

LiveGBS作为上级平台对接海康大华华为宇视等下级平台监控摄像机NVR硬件执法仪等GB28181设备 1、背景说明2、部署国标平台2.1、安装使用说明2.2、服务器网络环境2.3、信令服务配置 3、监控摄像头设备接入3.1、海康GB28181接入示例3.2、大华GB28181接入示例3.3、华为IPC GB28181接…

SpringBoot整合ZooKeeper完整教程

目录 ZooKeeper简单介绍 一、安装zookeeper 二、springboot整合zookeeper ZooKeeper简单介绍 zookeeper是为分布式应用程序提供的高性能协调服务。zookeeper将命名、配置管理、同步和组服务等常用服务公开在一个简单的接口中&#xff0c;因此用户无需从头开始编写这些服务。可…

Android GridPager实战,从RecyclerView to ViewPager

这个简单的的案例展示了如何从RecyclerView to ViewPager&#xff0c;以网上的公开图片为样例。 安卓开发中从RecyclerView 到 ViewPager demo运行结果demo项目工程目录结构关键代码 MainActivity关键代码GridFragment关键代码ImageFragment关键代码ImagePagerFragment关键布局…