Vectorul de frecvene i aplicaii
Vectorul de frecvene reine numrul de apariii al fiecrei valori citite ntr-un vector. Folosirea
vectorului de frecvene permite scrierea unor algoritmi eficieni n cazul n care datele de intrare au valori
dintr-un domeniu cunoscut care poate fi prelucrat rapid. Folosirea unui vector de frecven sau
marcare este eficient numai n cazul n care valorile care intereseaz sunt ntregi i numrul
valorilor distincte posibile este cel mult 1.000.000 pentru un timp maxim de 1 sec/test.
De exemplu acest vector poate fi folosit pentru sortarea rapid a datelor, n timp liniar.
Tot cu ajutorul acestui vector pot fi implementate operaiile de baz cu mulimi:
- Cutarea unui element
- Intersecia a dou (sau mai multe) mulimi
- Reuniunea a dou (sau mai multe) mulimi
n orice mulime elementele sunt unice, iar vectorul frecvenelor are doar valori 0 sau 1. Acest vector
este numit vectorul caracteristic al unei mulimi. Vectorul de frecvene poate fi folosit pentru a obine
rapid mulimea asociat ca un vector caracteristic astfel:
- 0 nseamn c elementul nu aparine mulimii
- o valoare diferit de 0 nseamn c elementul aparine mulimii
APLICAII ale vectorului de frecvene sau vectorului caracteristic al unei mulimi:
1. Prelucrarea cifrelor
2. Sortare n timp liniar
3. Operaii cu mulimi
1. Prelucrarea cifrelor unui numr
Aplicaie rezolvat Cifre distincte:
Fiind dat un numr natural n ntre 1 i dou miliarde s se afieze cifrele i numrul de
elemente al mulimii cifrelor sale.
Date de intrare
Fiierul de intrare [Link] conine numrul n.
Date de ieire
Fiierul de ieire [Link] va conine un singur numr, numrul de cifre distincte ale lui n.
Restricii
1 n [Link]
Exemplu
[Link] [Link]
234234234 3
Explicaie
Numrul 234234234 conine 3 cifre distincte, 2, 3 i 4.
Vectorul de frecven pentru cifrele unui numr se declar sub forma unui vector cu 10 componente, de la
a[0],,a[9]. Acestea vor fi iniializate cu 0, iar dup citirea numrului n se va incrementa cu 1 numrul
apariiilor pentru fiecare cifr a lui n.
Atenie! Vectorul de frecvene nu permite refacerea numrului citit iniial, dac este necesar valoarea
acestuia trebuie memorat separat.
Soluie: Codul C++ este dat n continuare:
1. #include<iostream>
2. using namespace std;
3. int a[10],n;
4.
5. int main()
6. {
7. int i,nn,nc=0;
8. cout<<"n=";
9. cin>>n;
10. nn=n;//clonam valoarea n in variabila nn
11. while(nn>0) //construim vectorul frecventelor
12. { a[nn%10]++;
13. nn=nn/10;}
14. //afisam cifrele distincte
15. for(i=0;i<10;i++)
16. if (a[i]>0) {cout<<i;nc++;}
17. cout<<'\n'<<nc<<" cifre distincte";
18. return 0;
19. }
1. Cifre comune: Se citesc dou numere naturale n i m. S se afieze numrul de cifre
distincte comune ambelor numere.
Indicaie de rezolvare: Construim vectorii de frecven pentru fiecare numr i apoi aflm
cifrele comune. Dac notm cu a vectorul de frecvene al lui n i cu b vectorul de frecvene
al lui b condiia ca cifra c s fie comun este a[c]>0 && b[c]>0.
2. Maxnr: Dat un numr natural n ntre 1 i dou miliarde s se afieze cel mai mare
numr care se poate forma cu cifrele sale.
Indicaie de rezolvare: Construim vectorul de frecvene asociat numrului n, notat cu a.
Numrul maxim care poate fi format cu cifrele sale se obine prin parcurgerea n ordine
descresctoare, de la 9 la 0, a vectorului de frecvene i scriind fiecare cifr c de a[c] ori.
3. Minnr: Dat un numr natural n ntre 1 i dou miliarde s se afieze cel mai mic numr
care se poate forma cu cifrele sale.
Indicaie de rezolvare: Construim vectorul de frecvene asociat numrului n, notat cu a.
Avem dou situaii posibile: a) numrul n nu are cifra 0 sau b) numrul n conine i cifra 0.
a) Numrul minim se obine prin parcurgerea n ordine cresctoare, de la 1 la 9, a
vectorului frecvenelor i afiarea fiecrei cifre c de a[c] ori.
b) Se determin prima cifr nenul a lui n i se afieaz ca prima cifr a rezultatului. Dup
prima cifr se afieaz toate zerourile care apar n n, iar apoi se aplic acelai algoritm
ca n cazul a.
4. Minnrk: Se citesc dou numere, n i k. S se afieze cel mai mic numr de k cifre care
se poate forma cu cifrele lui n.
Indicaie de rezolvare: Construim vectorul de frecvene asociat numrului n, notat cu a.
Avem dou situaii posibile: a) numrul n nu are cifra 0 sau b) numrul n conine i cifra 0.
Aplicm acelai algoritm de la problema Minnr, dar afim doar primele k cifre din numrul
rezultat.
5. Cifre1: Se dau dou numere naturale a i b cu maxim 9 cifre.
a) S se determine cifrele distincte, comune numerelor a i b.
b) S se afieze numrul cel mai mare format din toate cifrele lui a i b.
2. Sortare n timp liniar
Culori (clasa a 5-a)
Se d o secven de n culori codificate cu numere ntre 1 i 99. S se afieze culorile n ordinea
lor cresctoare. Acesta este un exerciiu introductiv n folosirea vectorilor de frecven.
Date de intrare
Fiierul de intrare [Link] va conine pe prima linie numrul n. Pe a doua linie va conine n
numere desprite prin spaiu.
Date de ieire
n fiierul de ieire [Link] vei scrie o singur linie coninnd cele n culori n ordine
cresctoare.
Restricii
1 n 1.000.000
1 culoare 99
Exemplu
[Link] [Link]
10
4 7 3 0 3 7 4 0 2 2
0 0 2 2 3 3 4 4 7 7
Explicaie
Cele zece culori de la intrare au fost afiate n ordine cresctoare.
Soluie
Construim vectorul de frecven a cifrelor a[0], , a[9] i afim cifrele n ordine cresctoare
de la 0 la 9, iar fiecare cifr c va fi scris de a[c] ori.
3. Operaii cu mulimi
A. ntr-o mulime n sens matematic - set, elementele au valori distincte iar vectorul de
frecvene se numete vector caracteristic. Dac mulimea A are valorile din mulimea
{0,1,2,,n} vectorul caracteristic al mulimii A este definit prin:
[] {
1. Iniializarea vectorului caracteristic:
1. void citire(int &n, int a[])
2. {
3. int i,x;
4. for(i=1;i<=n;i++)
5. {cin>>x;
6. a[x]++;}
7. }
2. Testarea apartenenei unui element x la mulimea A:
1. int apartine(int x,int a[])
2. {
3. if(a[x]>0) return 1;
4. else return 0;
5. }
3. Intersecia a dou mulimi A i B de numere naturale din intervalul nchis [0,n].
1. void intersectie(int n,int a[],int b[])
2. { int i;
3. for(i=0;i<=n;i++)
4. if(a[i]*b[i]>0) cout<<i;
5. }
4. Reuniunea a dou mulimi A i B de numere naturale din intervalul nchis [0,n].
1. void reuniune(int n,int a[],int b[])
2. { int i;
3. for(i=0;i<=n;i++)
4. if(a[i]+b[i]>0) cout<<i;
5. }
5. Diferena a dou mulimi A i B de numere naturale din intervalul nchis [0,n].
1. void diferenta(int n,int a[],int b[])
2. { int i;
3. for(i=0;i<=n;i++)
4. if(a[i]>0 && b[i]==0) cout<<i;
5. }
B. O mulime generalizat sau multiset este o colecie de elemente n care este permis ca o
valoare s se repete. Valorile care se repet pot fi considerate identice sau echivalente. De
exemplu, ntr-o list de persoane pot s existe mai multe persoane care au aceeai nlime
sau cu acelai prenume.
Vectorul de frecven reine numrul de apariii al unei valori din multiset:
[]
Citirea i testul de apartenen sunt identice cu cele de la mulimi.
1. Intersecia a dou mulimi generalizate A i B de numere naturale din intervalul nchis [0,n].
1. void intersectie(int n,int a[],int b[],int c[])
2. { int i;
3. for(i=0;i<=n;i++)
4. if(a[i]<=b[i]) c[i]=a[i];
5. else c[i]=a[i];
6. }
2. Reuniunea a dou mulimi generalizate A i B de numere naturale din intervalul nchis [0,n].
1. void reuniune(int n,int a[],int b[],int c[])
2. { int i;
3. for(i=0;i<=n;i++)
4. if(a[i]<=b[i]) c[i]=b[i];
5. else c[i]=a[i];
6. }
3. Diferena a dou mulimi generalizate A i B de numere naturale din intervalul nchis [0,n].
1. void diferenta(int n,int a[],int b[],int c[])
2. { int i;
3. for(i=0;i<=n;i++)
4. if(a[i]>b[i]) c[i]=a[i]-b[i];
5. else c[i]=0;
6. }
4. Sortarea cresctoare elementelor unei mulimi generalizate se face printr-o simpl parcurgere a
intervalului [0,n] .
1. void tipar(int n,int a[])
2. { int i,j;
3. for(i=0;i<=n;i++)
4. for(j=0;j<=a[i];j++)
5. cout<<i<<' ';
6. }