Open In App

Boyer-Moore Majority Voting Algorithm for Searching elements having more than K Occurrences

Last Updated : 02 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

The Boyer-Moore Majority Voting Algorithm is a well-known and efficient algorithm used to find the majority element in an array, i.e., an element that appears more than n/2 times. This algorithm, initially designed by Robert S. Boyer and J Strother Moore in 1981, is widely used in various applications, including data analysis and stream processing. However, in some scenarios, we may need to find elements that occur more than n/k times, where k is a positive integer. In this article, we explore the generalization of the Boyer-Moore Majority Voting Algorithm to solve this problem efficiently.

Understanding Boyer-Moore Majority Voting Algorithm:

Before we dive into the generalization of the algorithm, let’s briefly review how the original Boyer-Moore Majority Voting Algorithm works.

1. Initialization: We start by initializing two variables, “candidate” and “count,” to null and 0, respectively.

2. Majority Element Detection: We iterate through the array and update the “candidate” and “count” variables as follows:

  • If “count” is 0, we set the current element as the “candidate.”
  • If the current element is equal to the “candidate,” we increment “count” by 1.
  • If the current element is different from the “candidate,” we decrement “count” by 1.

3. Verification: After the iteration, the “candidate” variable stores a potential majority element. We then perform a second pass to verify if the “candidate” indeed appears more than n/2 times in the array.

Time Complexity: O(N).
Auxiliary Space: O(1).

If you want to know more about Boyer-Moore Majority Voting Algorithm you can click here.

Generalizing for n/k Occurrences:

The Boyer-Moore Majority Voting Algorithm is a powerful tool for finding the majority element in an array, i.e., an element that appears more than n/2 times, where n is the size of the array. But what if we need to find elements that occur more than n/k times, where k is any positive integer? In this article, we’ll make this algorithm more accessible and show you how to adapt it for this general scenario.

Understanding the Modified Algorithm

To extend the Boyer-Moore Majority Voting Algorithm to find elements that appear more than n/k times, we’ll need to make a few tweaks. Here’s a simplified version:

1. Initialization: Start by creating an array with k-1 slots, each storing a pair of values (element, count) to represent potential candidates and their counts. Additionally, keep two variables, count_others and count_cleared, both initially set to 0.

2. Scanning the Array: Traverse through the array, and for each element, follow these steps:

  • If the element already exists in one of the k-1 slots, increment its count.
  • If there’s an empty slot in the array, insert the current element as a new candidate with a count of 1.
  • If neither of the above conditions applies, decrease the count of all candidates by 1.

3. Verification: After this step, you’ll have k-1 candidates along with their counts. To identify the elements occurring more than n/k times, iterate through the array once more. For each candidate, check if its actual count is greater than n/k. Additionally, keep track of elements cleared from the candidates during the scanning step using the count_cleared variable.

Below is the implementation of the above idea:

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
vector<int> majorityElement(vector<int>& nums, int k)
{
    int n = nums.size();
 
    // Initialize an array of pairs to store k-1
    // candidates and their counts
    vector<pair<int, int> > candidates(k - 1);
 
    // Initialize candidate elements
    // and their counts to 0
    for (int i = 0; i < k - 1; i++) {
        candidates[i] = { 0, 0 };
    }
 
    // Step 1: Scanning the Array
    for (int num : nums) {
        bool found = false;
        for (int j = 0; j < k - 1; j++) {
 
            // If the element exists in
            // candidates
            if (candidates[j].first == num) {
 
                // Increment its count
                candidates[j].second++;
                found = true;
                break;
            }
        }
        // If the element is not in candidates
        if (!found) {
            for (int j = 0; j < k - 1; j++) {
 
                // Find an empty slot
                if (candidates[j].second == 0) {
 
                    // Insert as a new candidate
                    candidates[j] = { num, 1 };
                    found = true;
                    break;
                }
            }
        }
 
        // If all slots are occupied
        if (!found) {
 
            // Decrement counts
            // of all candidates
            for (int j = 0; j < k - 1; j++) {
                candidates[j].second--;
            }
        }
    }
 
    // Initialize a vector to store
    // the final results
    vector<int> ans;
 
    // Step 2: Verification
    for (int i = 0; i < k - 1; i++) {
        int count = 0;
        for (int j = 0; j < n; j++) {
            if (nums[j] == candidates[i].first) {
                count++;
            }
        }
 
        // If the count is greater than n/k
        if (count > n / k) {
 
            // Add the candidate
            // to the result
            ans.push_back(candidates[i].first);
        }
    }
 
    return ans;
}
 
// Drivers code
int main()
{
    vector<int> nums = { 3, 2, 3 };
    int k = 3;
    vector<int> result = majorityElement(nums, k);
 
    cout << "Elements occurring more than "
         << nums.size() / k << " times: ";
    for (int num : result) {
        cout << num << " ";
    }
    cout << endl;
 
    return 0;
}


Java




import java.util.ArrayList;
import java.util.List;
 
public class MajorityElement {
    public List<Integer> majorityElement(int[] nums, int k) {
        int n = nums.length;
        int[][] candidates = new int[k - 1][2];
         
        for (int i = 0; i < k - 1; i++) {
            candidates[i] = new int[]{0, 0};
        }
         
        for (int num : nums) {
            boolean found = false;
            for (int j = 0; j < k - 1; j++) {
                if (candidates[j][0] == num) {
                    candidates[j][1]++;
                    found = true;
                    break;
                }
            }
            if (!found) {
                for (int j = 0; j < k - 1; j++) {
                    if (candidates[j][1] == 0) {
                        candidates[j][0] = num;
                        candidates[j][1] = 1;
                        found = true;
                        break;
                    }
                }
            }
            if (!found) {
                for (int j = 0; j < k - 1; j++) {
                    candidates[j][1]--;
                }
            }
        }
         
        List<Integer> ans = new ArrayList<>();
        for (int[] candidate : candidates) {
            int count = 0;
            for (int num : nums) {
                if (num == candidate[0]) {
                    count++;
                }
            }
            if (count > n / k) {
                ans.add(candidate[0]);
            }
        }
         
        return ans;
    }
}


Python




def majority_element(nums, k):
    n = len(nums)
    candidates = [None] * (k-1# Initialize an array to store k-1 candidates
     
    # Initialize candidate elements and their counts to 0
    for i in range(k-1):
        candidates[i] = [0, 0]
     
    # Step 1: Scanning the Array
    for num in nums:
        found = False
        for j in range(k-1):
            if candidates[j][0] == num:  # If the element exists in candidates
                candidates[j][1] += 1    # Increment its count
                found = True
                break
        if not found:  # If the element is not in candidates
            for j in range(k-1):
                if candidates[j][1] == 0# Find an empty slot
                    candidates[j] = [num, 1# Insert as a new candidate
                    found = True
                    break
        if not found:  # If all slots are occupied
            for j in range(k-1):
                candidates[j][1] -= 1  # Decrement counts of all candidates
     
    ans = []  # Initialize a list to store the final results
     
    # Step 2: Verification
    for candidate in candidates:
        count = nums.count(candidate[0])  # Count actual occurrences of each candidate
        if count > n // k:  # If the count is greater than n/k
            ans.append(candidate[0])  # Add the candidate to the result
     
    return ans


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
class Program {
    static List<int> MajorityElement(List<int> nums, int k)
    {
        int n = nums.Count;
 
        // Initialize an array of tuples to store k-1
        // candidates and their counts
        var candidates = new List<Tuple<int, int> >(k - 1);
 
        // Initialize candidate elements and their counts to
        // 0
        for (int i = 0; i < k - 1; i++) {
            candidates.Add(new Tuple<int, int>(0, 0));
        }
 
        // Step 1: Scanning the Array
        foreach(int num in nums)
        {
            bool found = false;
            for (int j = 0; j < k - 1; j++) {
                // If the element exists in candidates
                if (candidates[j].Item1 == num) {
                    // Increment its count
                    candidates[j] = Tuple.Create(
                        candidates[j].Item1,
                        candidates[j].Item2 + 1);
                    found = true;
                    break;
                }
            }
 
            // If the element is not in candidates
            if (!found) {
                for (int j = 0; j < k - 1; j++) {
                    // Find an empty slot
                    if (candidates[j].Item2 == 0) {
                        // Insert as a new candidate
                        candidates[j]
                            = Tuple.Create(num, 1);
                        found = true;
                        break;
                    }
                }
            }
 
            // If all slots are occupied
            if (!found) {
                // Decrement counts of all candidates
                for (int j = 0; j < k - 1; j++) {
                    candidates[j] = Tuple.Create(
                        candidates[j].Item1,
                        candidates[j].Item2 - 1);
                }
            }
        }
 
        // Initialize a list to store the final results
        List<int> ans = new List<int>();
 
        // Step 2: Verification
        for (int i = 0; i < k - 1; i++) {
            int count = 0;
            foreach(int num in nums)
            {
                if (num == candidates[i].Item1) {
                    count++;
                }
            }
 
            // If the count is greater than n/k
            if (count > n / k) {
                // Add the candidate to the result
                ans.Add(candidates[i].Item1);
            }
        }
 
        return ans;
    }
 
    static void Main(string[] args)
    {
        List<int> nums = new List<int>{ 3, 2, 3 };
        int k = 3;
        List<int> result = MajorityElement(nums, k);
 
        Console.Write("Elements occurring more than "
                      + nums.Count / k + " times: ");
        foreach(int num in result)
        {
            Console.Write(num + " ");
        }
        Console.WriteLine();
    }
}


Javascript




function majorityElement(nums, k) {
    const n = nums.length;
    const candidates = new Array(k - 1);
     
    for (let i = 0; i < k - 1; i++) {
        candidates[i] = [0, 0];
    }
     
    for (const num of nums) {
        let found = false;
        for (let j = 0; j < k - 1; j++) {
            if (candidates[j][0] === num) {
                candidates[j][1]++;
                found = true;
                break;
            }
        }
        if (!found) {
            for (let j = 0; j < k - 1; j++) {
                if (candidates[j][1] === 0) {
                    candidates[j] = [num, 1];
                    found = true;
                    break;
                }
            }
        }
        if (!found) {
            for (let j = 0; j < k - 1; j++) {
                candidates[j][1]--;
            }
        }
    }
    


Output

Elements occurring more than 1 times: 3 



Time Complexity: O(n*k)
Auxiliary Space: O(k)

Conclusion:

In summary, the Boyer-Moore Majority Voting Algorithm, originally designed to find the majority element in an array, can be adapted to detect elements that appear more than n/k times efficiently. By modifying the initialization, scanning, and verification steps as outlined above, you can apply this generalized algorithm in various situations where you need to find elements with specific frequency requirements. This versatile algorithm is a valuable tool for data analysis, stream processing, and many other applications where efficient majority element detection is essential.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads