Najčešća ocena
Dato je n ocena od 1 do 5 (1 ≤ n ≤ 106). Ispiši ocenu koja se javlja najviše puta; ako ih ima više, najmanju od njih.
Primer
Ulaz
8
4 5 3 4 5 4 2 5Izlaz
4Kada su vrednosti elemenata mali celi brojevi (na primer ocene 1–5 ili brojevi od 0 do milion), niz može da se sortira bez ijednog poređenja: prebrojimo koliko puta se javlja svaka vrednost i ispišemo ih redom. To radi u vremenu O(n + K), gde je K najveća vrednost.
Za niz 3 1 4 1 0 3 3 sa vrednostima od 0 do 4 pravimo niz brojača br, gde je br[v] broj pojavljivanja vrednosti v:
| v | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| br[v] | 1 | 2 | 0 | 3 | 1 |
Sortiran niz dobijamo kada ispišemo vrednost 0 jednom, 1 dva puta, 2 nijednom, 3 tri puta i 4 jednom: 0 1 1 3 3 3 4.
#include <iostream>
#include <vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
const int K = 1000000; // najveća moguća vrednost
int n;
cin >> n;
vector<int> br(K + 1, 0); // br[v] = koliko puta se javlja v
for (int i = 0; i < n; i++) {
int x;
cin >> x;
br[x]++;
}
for (int v = 0; v <= K; v++) // ispisujemo vrednosti redom
for (int k = 0; k < br[v]; k++)
cout << v << " ";
cout << "\n";
return 0;
}
Algoritam prolazi jednom kroz niz (n koraka) i jednom kroz sve moguće vrednosti (K koraka). Isplati se kada K nije mnogo veće od n, a ne može se koristiti za realne brojeve ni za vrednosti do 109 (niz brojača bi bio prevelik).
| Situacija | Prebrojavanje? |
|---|---|
| 106 ocena od 1 do 5 | da – idealno |
| 105 brojeva od 0 do 106 | da |
| 1000 brojeva do 109 | ne – koristi sort |
| negativni brojevi od −1000 do 1000 | da, uz pomeraj: br[x + 1000]++ |
Isti niz brojača često je i cilj zadatka: najčešća vrednost, broj različitih vrednosti, da li se neka vrednost ponavlja – sve se čita iz br.
Kada sortiramo cele zapise (na primer učenike po oceni), ne smemo samo da ispišemo ocene. Tada iz brojača računamo početnu poziciju svake vrednosti (prefiksni zbirovi – vidi prefiksne sume) i zapise prepisujemo redom na njihova mesta. Redosled učenika sa istom ocenom ostaje isti – sortiranje je stabilno.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
int n;
cin >> n;
vector<string> ime(n);
vector<int> ocena(n);
for (int i = 0; i < n; i++) cin >> ime[i] >> ocena[i];
vector<int> poc(7, 0); // ocene 1..5
for (int i = 0; i < n; i++) poc[ocena[i] + 1]++;
for (int v = 1; v <= 6; v++) poc[v] += poc[v - 1]; // poc[v] = prva pozicija za ocenu v
vector<string> rez(n);
for (int i = 0; i < n; i++) rez[poc[ocena[i]]++] = ime[i];
for (auto &s : rez) cout << s << " ";
cout << endl;
return 0;
}
Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.
Dato je n ocena od 1 do 5 (1 ≤ n ≤ 106). Ispiši ocenu koja se javlja najviše puta; ako ih ima više, najmanju od njih.
8
4 5 3 4 5 4 2 54Dato je n brojeva od 1 do 106. Ispiši prvi broj (gledano sleva) čije se pojavljivanje već desilo ranije u nizu, ili NEMA.
6
7 3 9 3 7 133
1 2 3NEMAK + 1 elemenata (indeksi od 0 do K).vector ili globalni niz, ne kao lokalni niz u main (stek je mali).br[x + M]).1. Koja je složenost sortiranja prebrojavanjem za n elemenata sa vrednostima od 0 do K?
2. Za koji ulaz NIJE pogodno sortiranje prebrojavanjem?
3. Koliko poređenja dva elementa radi ovaj algoritam?