Boyer-Moore 多数投票算法
Boyer-Moore 投票算法是流行的最优算法之一,用于在给定元素中找到出现次数超过 N/2 的多数元素。这对于查找对给定元素进行 2 次遍历的多数元素非常有效,这在 O(N) 时间复杂度和 O(1) 空间复杂度下工作。
让我们通过一个例子来看看其工作背后的算法和直觉 -
Input :{1,1,1,1,2,3,5}
Output : 1
Explanation : 1 occurs more than 3 times.
Input : {1,2,3}
Output : -1
该算法的工作原理是,如果一个元素出现超过 N/2 次,则意味着除此之外的其余元素肯定会小于 N/2。因此,让我们检查算法的进程。
- 首先,从给定的元素集合中选择一个候选元素,如果它与候选元素相同,则增加投票。否则,如果票数变为0,则减少票数,选择另一个新元素作为新候选人。
工作背后的直觉:
当元素与候选元素相同时,当发现其他元素不等于候选元素时,投票增加。我们减少了计数。这实际上意味着我们正在降低所选候选人的获胜能力的优先级,因为我们知道如果候选人占多数,它会出现 N/2 次以上,而其余元素少于 N/2。我们不断减少投票,因为我们发现了一些与候选元素不同的元素。当票数变为 0 时,这实际上意味着存在相同数量的不同元素,这不应该是该元素成为多数元素的情况。所以候选元素不可能是多数,所以我们选择当前元素作为候选元素并继续相同,直到所有元素都完成。最后的候选人将是我们的多数派。我们使用第二次遍历来检查它的计数是否大于 N/2。如果是真的,我们认为它是多数元素。
实现算法的步骤:
第 1 步 –找到占多数的候选人 –
- 初始化一个变量说i ,votes = 0, Candidate =-1
- 使用for循环遍历数组
- 如果votes = 0,选择候选人 = arr[i] ,使votes=1 。
- 否则,如果当前元素与候选增量投票相同
- 否则减少选票。
第 2 步 -检查候选人是否有超过 N/2 票 -
- 初始化一个变量count = 0,如果它与候选者相同,则增加count。
- 如果计数 >N/2,则返回候选者。
- 否则返回-1。
Dry run for the above example:
Given :
arr[]= 1 1 1 1 2 3 5
votes =0 1 2 3 4 3 2 1
candidate = -1 1 1 1 1 1 1 1
candidate = 1 after first traversal
1 1 1 1 2 3 5
count =0 1 2 3 4 4 4 4
candidate = 1
Hence count > 7/2 =3
So 1 is the majority element.
C++
// C++ implementation for the above approach
#include
using namespace std;
// Function to find majority element
int findMajority(int arr[], int n)
{
int i, candidate = -1, votes = 0;
// Finding majority candidate
for (i = 0; i < n; i++) {
if (votes == 0) {
candidate = arr[i];
votes = 1;
}
else {
if (arr[i] == candidate)
votes++;
else
votes--;
}
}
int count = 0;
// Checking if majority candidate occurs more than n/2
// times
for (i = 0; i < n; i++) {
if (arr[i] == candidate)
count++;
}
if (count > n / 2)
return candidate;
return -1;
}
int main()
{
int arr[] = { 1, 1, 1, 1, 2, 3, 4 };
int n = sizeof(arr) / sizeof(arr[0]);
int majority = findMajority(arr, n);
cout << " The majority element is : " << majority;
return 0;
}
Java
import java.io.*;
class GFG
{
// Function to find majority element
public static int findMajority(int[] nums)
{
int count = 0, candidate = -1;
// Finding majority candidate
for (int index = 0; index < nums.length; index++) {
if (count == 0) {
candidate = nums[index];
count = 1;
}
else {
if (nums[index] == candidate)
count++;
else
count--;
}
}
// Checking if majority candidate occurs more than
// n/2 times
count = 0;
for (int index = 0; index < nums.length; index++) {
if (nums[index] == candidate)
count++;
}
if (count > (nums.length / 2))
return candidate;
return -1;
// The last for loop and the if statement step can
// be skip if a majority element is confirmed to
// be present in an array just return candidate
// in that case
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 1, 1, 1, 1, 2, 3, 4 };
int majority = findMajority(arr);
System.out.println(" The majority element is : "
+ majority);
}
}
// This code is contribute by Arnav Sharma
Python3
# Python implementation for the above approach
# Function to find majority element
def findMajority(arr, n):
candidate = -1
votes = 0
# Finding majority candidate
for i in range (n):
if (votes == 0):
candidate = arr[i]
votes = 1
else:
if (arr[i] == candidate):
votes += 1
else:
votes -= 1
count = 0
# Checking if majority candidate occurs more than n/2
# times
for i in range (n):
if (arr[i] == candidate):
count += 1
if (count > n // 2):
return candidate
else:
return -1
# Driver Code
arr = [ 1, 1, 1, 1, 2, 3, 4 ]
n = len(arr)
majority = findMajority(arr, n)
print(" The majority element is :" ,majority)
# This code is contributed by shivanisinghss2110
C#
using System;
class GFG
{
// Function to find majority element
public static int findMajority(int[] nums)
{
int count = 0, candidate = -1;
// Finding majority candidate
for (int index = 0; index < nums.Length; index++) {
if (count == 0) {
candidate = nums[index];
count = 1;
}
else {
if (nums[index] == candidate)
count++;
else
count--;
}
}
// Checking if majority candidate occurs more than
// n/2 times
count = 0;
for (int index = 0; index < nums.Length; index++) {
if (nums[index] == candidate)
count++;
}
if (count > (nums.Length / 2))
return candidate;
return -1;
// The last for loop and the if statement step can
// be skip if a majority element is confirmed to
// be present in an array just return candidate
// in that case
}
// Driver code
public static void Main(String[] args)
{
int []arr = { 1, 1, 1, 1, 2, 3, 4};
int majority = findMajority(arr);
Console.Write(" The majority element is : "
+ majority);
}
}
// This code is contributed by shivanisinghss2110
Javascript
输出
The majority element is : 1
时间复杂度: O(n)(两次遍历数组)
空间复杂度: O(1)