Clasa a XII-a · Tehnici avansate: doi pointeri, căutare binară pe răspuns, stive monotoneRead in English
Element majoritar (Boyer-Moore) în C++
În engleză: Majority element (Boyer-Moore)
Ideea
Elementul majoritar apare de mai mult de n / 2 ori. Algoritmul de vot ține un candidat și un contor: o valoare egală cu candidatul crește contorul, una diferită îl scade, iar la contor 0 valoarea curentă devine candidat. Ideea: dacă „anulăm” perechi de valori diferite, majoritarul nu poate fi anulat complet. Prima trecere dă doar un candidat, așa că a doua trecere numără aparițiile lui și verifică dacă e chiar majoritar. Funcționează pentru valori oricât de mari (nu are nevoie de vector de frecvență).
Descrierea în engleză
The majority element appears more than n / 2 times. The voting algorithm keeps a candidate and a counter: a value equal to the candidate increases the counter, a different one decreases it, and when the counter is 0 the current value becomes the candidate. The idea: if we 'cancel out' pairs of different values, the majority cannot be cancelled completely. The first pass only gives a candidate, so a second pass counts its occurrences and checks that it really is the majority. It works for arbitrarily large values (no frequency array needed).
- Complexitate
- O(n) timp, O(1) memorie suplimentară
- Clasa
- Clasa a XII-a (Grade 12)
Exemple
Intrare
9 3 1 3 3 2 3 3 1 3
Ieșire așteptată
3
Intrare
4 1 2 1 2
Ieșire așteptată
nu exista
Codul C++
Codul complet, cu comentarii în română. Îl poți modifica liber și îl poți reseta oricând.
/*
* Titlu: Element majoritar (Boyer-Moore)
* Clasa: 12
* Capitol: Tehnici avansate: doi pointeri, căutare binară pe răspuns, stive monotone
* Descriere: Elementul majoritar apare de mai mult de n / 2 ori. Algoritmul de
* vot ține un candidat și un contor: o valoare egală cu candidatul
* crește contorul, una diferită îl scade, iar la contor 0 valoarea
* curentă devine candidat. Ideea: dacă „anulăm” perechi de valori
* diferite, majoritarul nu poate fi anulat complet. Prima trecere dă
* doar un candidat, așa că a doua trecere numără aparițiile lui și
* verifică dacă e chiar majoritar. Funcționează pentru valori oricât
* de mari (nu are nevoie de vector de frecvență).
* Complexitate: O(n) timp, O(1) memorie suplimentară
*
* Exemplu
* Intrare:
* 9
* 3 1 3 3 2 3 3 1 3
* Ieșire: 3
*
* Exemplu
* Intrare:
* 4
* 1 2 1 2
* Ieșire: nu exista
*/
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n;
cin >> n;
vector<long long> a(n);
for (int i = 0; i < n; i++)
cin >> a[i];
long long candidat = 0;
int contor = 0;
for (int i = 0; i < n; i++)
{
if (contor == 0)
{
candidat = a[i];
contor = 1;
}
else if (a[i] == candidat)
contor++;
else
contor--;
}
int aparitii = 0;
for (int i = 0; i < n; i++)
if (a[i] == candidat)
aparitii++;
if (2 * aparitii > n)
cout << candidat << '\n';
else
cout << "nu exista\n";
return 0;
}
Rulează pe un g++ adevărat (C++17, -O2) prin Compiler Explorer. Programele trebuie să se termine repede: există o limită de timp.