【转】摩尔投票算法详解
版权声明:本文为csdn博主yealxxy原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u014248127/article/details/79230221
摩尔投票算法也可以叫做多数投票算法,是我在看到 leetcode 169(Majority Element)题目时看到的算法。这篇文章从 leetcode 169(Majority Element)出发讲解摩尔投票算法的原理和优势,同时从 leetcode 229(Majority Element2)出发讲解摩尔投票算法的改进和推广。(本文所有代码都是python代码)
一、Majority Element题目介绍:给定一个长度为n的数组的时候,找出其中的主元素,即该元素在数组中出现的次数大于n/2的取整。题目中已经假定所给的数组一定含有元素,且主元素一定存在。一下是一些常用方法:
1,用字典遍历每个元素,并计数(python):
dic = {} for x in nums: if x in dic: dic[x] += 1 else: dic[x] = 1 for key,value in dic.items(): if value > len(nums)/2: return key
2,排序法:排序后,出现次数大于一半的肯定在中间(python)
nums.sort() return nums[len(nums)//2]
二、摩尔投票算法:摩尔投票算法的时间和空间都很低,时间复杂度为O(n),空间复杂度为O(1),这也是选择遮盖算法的原因。
1,算法原理:每次从数组中找出一对不同的元素,将它们从数组中删除,直到遍历完整个数组。由于这道题已经说明一定存在一个出现次数超过一半的元素,所以遍历完数组后数组中一定会存在至少一个元素。
算法在局部变量中定义一个序列元素(m)和一个计数器(i),初始化的情况下计数器为0;
算法依次扫描序列中的元素,当处理元素x的时候,如果计数器为0,那么将x赋值给m,然后将计数器(i)设置为1;
如果计数器不为0,那么将序列元素m和x比较,如果相等,那么计数器加1,如果不等,那么计数器减1。
处理之后,最后存储的序列元素(m),就是这个序列中最多的元素。
(如果不确定是否存储的元素m是最多的元素,还可以进行第二遍扫描判断是否为最多的元素)
2,算法伪代码(python):
初始化元素m=0,计数器count=0; 遍历数组中的每个数x: if i = 0: m = x and count = 1 else if m = x: count = count + 1 else: count = count − 1 Return m
3,Majority Element的摩尔投票算法求解(C++):
class Solution { public: bool check_Solution(vector<int> &numbers,int x){ int cnt=0,len=numbers.size(); for(int i=0;i<len;i++){ if(numbers[i]==x) cnt++; } return (2*cnt>len)?true:false; } int MoreThanHalfNum_Solution(vector<int> numbers) { if(numbers.size()==0) return 0; int cnt=0,num; for(int i=0;i<numbers.size();i++){ if(cnt==0){ num=numbers[i]; cnt==1; } if(num==numbers[i]) cnt++; else cnt--; } if(check_Solution(numbers,num)) return num; else return 0; } };
三、摩尔投票算法的改进:
1,题目: LeetCode 229 [Majority Element II]
给定一个整型数组,找到所有主元素,它在数组中的出现次数严格大于数组元素个数的三分之一。
算法:每次删除三个不相同的数,最后留下的一定是出现次数超过1/3的数,这个思想可以推广到出现次数超过1/k次的元素有哪些。
因为出现次数大于n/3的元素最多只有两个,所以最开始可以维护两个数字(num1,num2)和两个计数器(counter1,counter2);
遍历数组,当数组中元素和num1或者num2相同,对应的counter1或者counter2加1;
如果counter1或counter2为0,将遍历到的该元素赋给num1或者nums2;
否则counter1和counter2都减1。
2,C++代码:
3,python代码:
num1,count1 = None,0 num2,count2 = None,0 for x in nums:# 算法核心,找出主要元素的候选值 if x == num1: count1 += 1 elif x == num2: count2 += 1 elif count1 == 0: num1,count1 = x,1 elif count2 == 0: num2,count2 = x,1 else: count1 -= 1 count2 -= 1 count1,count2 = 0,0 for x in nums:# 统计确定候选值是真的主要元素 if x == num1: count1 += 1 if x == num2: count2 += 1 res = [] if count1 > len(nums)//3: res.append(num1) if count2 > len(nums)//3: res.append(num2) return res
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步