Șiruri care folosesc la... prelucrarea șirurilor Din secretele ȘIRURILORSorin GrozaAnaliza problemelor de
informatică este o etapă care nu trebuie "sărită" niciodată. Pentru
a vă convinge, vă prezentăm câteva "artificii" care îmbunătățesc
în mod considerabil timpul de execuție al algoritmilor. Nu vă speriați,
știm că această parte a GInfo se adresează "piticilor"; nu vom intra
în prea multe detalii.
Problema 1: Numărul lipsăSe citește de la tastatură un număr natural n și apoi n numere naturale distincte din intervalul [0,n]. Deoarece în intervalul [0,n] sunt n+1 numere naturale, rezultă că unul dintre numere lipsește. Scrieți un program care afișează numărul absent. Date de intrare: n=7 2 6 1 4 7 0 5 Date de ieșire: lipseste numarul 3 Rezolvare: Prima idee de rezolvare a problemei constă în a păstra într-un șir toate cele n numere și apoi, pentru fiecare număr de la 0 la n, trebuie verificat dacă este prezent sau nu în șir. În momentul în care se descoperă primul număr absent, acesta se va afișa, deoarece se știe că lipsește unul singur. O altă idee este de a ordona crescător șirul numerelor. Se verifică apoi diferența dintre fiecare două elemente consecutive. Când aceasta este diferită de 1, atunci a fost găsit numărul lipsă. Ambii algoritmi au un timp de răspuns mare, pentru o valoare mare a lui n.
Vom prezenta o implementare bazată pe prima idee, dar care nu necesită căutarea fiecăruia dintre numere, ceea ce ar putea însemna, în cazul cel mai defavorabil, parcurgerea integrală a șirului dat, de n ori. Pentru a evita aceste parcurgeri, vom folosi un șir v având n elemente, în care elementul v[i] indică prezența numărului i în șir. În momentul introducerii valorii i în șirul a, v[i] devine true. Este clar că în final toate elementele șirului vor fi egale cu true, mai puțin unul care rămâne cu valoarea false. Pentru a afla care este numărul absent, vom parcurge șirul v, iar elementul v[i]=false semnalează faptul că numărul i nu există în șirul dat.
Listing: ABSENT.PAS Program Absent; const n_max=100; var n,i:Integer; gasit:Boolean; v:array[0..n_max] of Boolean; a:array[0..n_max] of Integer; Begin Write('n= '); Readln(n); Writeln(n,' numere distincte'); for i:=0 to n_max do v[i]:=false; for i:=1 to n do begin Read(a[i]); v[a[i]]:=true end; Readln; gasit:=false; i:=0; while not gasit do if v[i] then Inc(i) else begin Writeln('Lipseste numarul ',i); gasit:=true end; Readln End. Problema 2: AeroportulUn grup de teroriști ce pregătesc o lovitură de stat, își propun să ocupe un aeroport strategic. Ei dețin harta zborurilor între cele n aeroporturi, adică m perechi (i,j) ce indică faptul că există zbor din aeroportul i în aeroportul j. Ei vor ocupa acel aeroport din care se poate ajunge în fiecare din celelalte aeroporturi, dar în care nu se poate ajunge. Scrieți un program care găsește aeroportul care trebuie ocupat. Date de intrare: n=3 m=3 1 3 2 1 2 3 Date de ieșire: Aeroportul ocupat este 2 Rezolvare: Trebuie găsit acel aeroport i, corespunzător numărului i care apare exact de n-1 ori în șirul care conține plecările din aeroporturi și de 0 ori în șirul care conține sosirile. Se va testa fiecare număr de la 1 la n dacă verifică această condiție. Când se găsește numărul, acesta se va afișa, deoarece reprezintă aeroportul căutat. Și în cazul acestei probleme se va folosi ideea de mai sus. Astfel, vom folosi 2 șiruri: un șir plec (plec[i] va arăta spre câte aeroporturi se poate zbura din aeroportul i); un alt șir sos (sos[j] va arăta din câte aeroporturi se poate ajunge în aeroportul j). Cum se construiesc cele 2 șiruri? Se citește o pereche (p s), iar plec[p] și sos[s] se măresc cu 1, deoarece s-a introdus faptul că din aeroportul p se pleacă, iar în aeroportul s se sosește. Se parcurg cele două șiruri, iar poziția pentru care plec[i]=n-1 și sos[i]=0 indică faptul că aeroportul este i. Listing: AEROPORT.PAS Program Aeroport; const n_max=100; var n,m,i,p,s:Integer; gasit:Boolean; plec,sos:array[0..n_max] of Integer; Begin Write('Numarul de aeroporturi: ); Readln(n); Write('Numarul legaturilor: '); Readln(m); for i:=1 to m do begin Write('Introduceti legatura ',i,': '); Read(p,s); Inc(plec[p]); Inc(sos[s]) end; Readln; gasit:=false; i:=0; while not gasit do begin if (plec[i]=n-1) and (sos[i]=0) then begin Writeln('Aeroportul ocupat este ',i); gasit:=true end; Inc(i) end; Readln End. Problema 3: Litera preferatăUn grup de n copii din clasa I sunt solicitați de către doamna învățătoare să noteze pe un bilețel litera (mică) preferată (după studiul alfabetului). Scrieți un program care afișează: - câte litere distincte ale alfabetului au fost folosite; - care este litera preferată a clasei și numărul copiilor care au ales-o. Date de intrare: n=10 a b a a c b d a c b Date de ieșire: 4 litere distincte litera preferata: a a fost aleasa de 4 copii Rezolvare: Pentru rezolvarea problemei vom folosi un șir litera cu 26 de elemente, unde litera[i] reprezintă de câte ori a fost aleasă litera de pe poziția i din alfabet (de exemplu litera[3] arată de câte ori a fost aleasă litera c). Se va parcurge șirul litera, iar numărul elementelor diferite de 0 va arăta câte litere distincte au fost folosite. Aflarea literei preferate se reduce astfel la aflarea maximului șirului cu frecvența literelor (fie acesta max) și a poziției acestuia (notată poz). Litera preferată este litera care se află pe poziția poz în alfabet și a fost aleasă de max copii. Pentru exemplul nostru poz=1, deci litera preferată este a și max=4, adică a fost aleasă de 4 copii. Cum se construieste șirul litera? În momentul citirii unei litere lit se va determina poziția ei în alfabet: pozitie=Ord(lit)-Ord('a')+1. Valoarea elementului litera[pozitie] se va mări cu 1. După citirea ultimei litere va fi construit șirul cu numărul de apariții a fiecărei litere introduse.
Listing ALFABET.PAS Program Alfabet; var n,i,max,Poz,pozitie,nr_lit:Integer; litera:array[1..26] of Integer; lit,ales:Char; Begin Write('Numarul de litere '); Readln(n); for i:=1 to n do begin Write('Introduceti litera ',i,' '); Readln(lit); pozitie:=Ord(lit)-Ord('a')+1; Inc(litera[pozitie]) end; for i:=1 to 26 do begin if litera[i]<>0 then Inc(nr_lit); if litera[i]>max then begin max:=litera[i]; Poz:=i end end; ales:=Chr(Poz+Ord('a')-1); Writeln(nr_lit,' litere distincte'); Writeln('Litera preferata: ',ales); Writeln('a fost aleasa de ',max,' copii'); End.
În încheiere vă propunem câteva probleme de rezolvat, pentru a oferi posibilitatea verificării modului de aplicare a ceea ce ați învățat nou din cele prezentate anterior. Problema 4: Moșul cel uitucMoșul cel bun a primit scrisori de la toți copiii cuminți, scrisori pe care le-a numerotat în ordinea sosirii, începând de la 1. Plecând la drum, se gândește că din grabă a uitat unele scrisori. Scoate din sac câte o scrisoare, una câte una, notând pe o foaie numărul fiecăreia. Știind că a primit n scrisori, scrieți un program care afișează cele pe care le-a uitat acasă. Se dă numărul de scrisori (n) și numerele scrisorilor existente în sac. Enumerarea lor se va termina cu 0 (zero). Date de intrare: n=10 8 3 6 1 7 2 10 5 0 Date de ieșire: Scrisori uitate: 4 9 Problema 5: Străzi și piețeÎntr-un oraș există n intersecții. Se citesc de la intrare perechi de forma (i j) cu semnificația că din intersecția i se poate ajunge direct în intersecția j fără a trece prin alte intersecții. Numim piață o intersecție în care numărul străzilor care intră, plus numărul străzilor care ies din ea este cel puțin 4. Piața centrală este intersecția cu cel mai mare număr de străzi care intră și care ies (este unică). Să se afle toate piețele și să se stabilească piața centrală. Observație: Sfârșitul perechilor este dat de perechea (0 0). Date de intrare: n=6 1 2 1 4 1 6 2 3 2 6 3 4 4 1 4 5 4 6 5 2 5 3 0 0 Date de ieșire: 3 piete: 1 2 4 piata centrala: 4 Problema 6: Și iar literePe plaja de la Năvodari au sosit copii care își petrec vacanța la mare. Profesorul însoțitor organizează următorul joc: copiii se împart în două grupe. Copiii din fiecare grupă vor scrie pe nisip litere ale alfabetului, obținându-se astfel două șiruri de litere. Apoi, toți copiii vor studia atent cele două șiruri de litere, dorind să descopere literele alfabetului care apar de același număr de ori în cele două șiruri. Un copil mai isteț, văzând care este jocul, scrie un program care, plecând de la cele două șiruri de litere, obține literele care apar de același număr de ori în cele două șiruri. Scrieți și voi un astfel de program. Date de intrare: msbsshbl - primul șir skxbbsmmsk - al doilea șir Date de ieșire: Litere cu acelasi numar de aparitii: s b
Domnul Sorin Groza este cadru didactic la Clubul Copiilor din Aiud; poate fi contactat prin intermediul redacției. [cuprins] |