Laborator 00: Intro to PA

PA = Proiectarea Algoritmilor

De ce PA?

“Before there were computers, there were algorithms. But now that there are computers, there are even more algorithms, and algorithms lie at the heart of computing.” (Introduction to Algorithms, 3rd edition, Thomas H. Cormen et al).

Ce este un algoritm?

O succesiune determinată de pași care prelucrează datele de intrare pentru a obține datele de ieșire dorite.

De ce avem nevoie de algoritmi eficienți?

Pentru unele aplicații, eficiența poate face diferența între un rezultat util și unul fără semnificație (ex. corect vs incorect), între un rezultat la timp și unul întârziat (ex. prelucarea real-time a datelor pe un computer de bord al unui avion) etc. Performanța algoritmilor din punct de vedere spațial, poate determina utilizarea lor în anumite tipuri de sistem (ex. sistemele embedded, din cauza spațiului de memorie redus, pot împiedica implementarea unui algoritm complex bazat pe mult caching).

De ce PA?

“Pentru că scrie în orar.” (Radu Nichita, 2021)
“Pentru că m-a pus mama să termin ACS.” (Cristian Olaru, 2021)
“Pentru că nu există seriale pe Netflix mai lungi decât laburile lui Darius.” (Miruna Banu, 2021)
“Gigel be with you!” (Darius-Florentin Neațu, 2017)

La PA se studiază principalele categorii de algoritmi, care reprezintă baza de gândire pentru un inginer în proiectarea și dezvoltarea viitoarelor sisteme, pornind de la probleme abstracte (ex. o problemă de tip parcurgere pe un graf neorientat se poate mapa pe găsirea unor sugestii de prietenie în rețele sociale precum Facebook).

Pe termen scurt, PA vă poate ajuta să vă pregătiți și pentru problemele de tip interviu (mai multe informații pe pagina ACS Prezentare internshipuri).

Ce vom face?

Vom aprofunda elementele fundamentale necesare rezolvării fiecărei clase de probleme analizate, prezentând mai mulți algoritmi pentru fiecare problemă studiată și evidențiind pe cei optimi (eficienți).

Pornind de la aceste elemente, vom accentua punctele de interes identificate, descoperind șabloane de rezolvare și modalități de construire a soluțiilor pentru o problemă.

Limbaje de programare

La PA este permisă folosirea limbajelor de programare: C++ / Java / C. Din cauză că aproape orice algoritm studiat se bazează pe folosirea unor structuri de date implementate deja, NU recomandăm folosirea limbajului C, întrucât bibliotecile standard nu le conțin.

De ce C++?

STL (Standard Template Library) din C++ reprezintă o bibliotecă generică de structuri de date și algoritmi, care facilitează implementarea rapidă și eficientă a algoritmilor studiați.

De ce Java?

Asemănător C++, Java Collections oferă implementarea tuturor structurilor și algoritmilor necesari la PA. De asemenea, a fost un limbaj deja studiat la POO.

De ce nu alte limbaje?

Considerăm că acestea sunt 2 limbaje foarte folosite și că, prin funcționalitățile oferite, studentul se poate concentra efectiv pe implementarea algoritmilor și nu pe alte aspecte legate de limbaj.

Coding Style

Recomandăm următoarele conveții de coding style:

Google C++ Style Guide

Google Java Style Guide

Debugging

Pe parcursul semestrului, vă poate fi util să știți cum se folosește un debugger pentru a găsi probleme într-un mod rapid. Vă recomandăm articolul PC@Debugging pentru a vă reaminti de cum folosim GDB atât din CLI cât și prin intermediul unui IDE.

Desfășurare laborator

În prima săptămână se va clona repo-ul de laborator conform instrucțiunilor de pe pagina pa-lab. În fiecare săptămână se rulează comanda “git pull” pentru obținerea scheletului actualizat înainte de fiecare laborator.

Secțiunile de Exerciții / Bonus / Extra reprezintă seturi de probleme grupate pe nivele de dificultate (de la ușor la greu). Recomandăm rezolvarea tuturor exercițiilor propuse, pentru înțelegerea algoritmilor studiați.

Exercitii

Task-uri:

  • Task00: Citiți README de pe pagina principala pa-lab. Alegeți un limbaj de programare dintre C++ și Java și parcurgeți tutorialul aferent din pa-lab::skel/lab00.
  • Task01: Se dă un vector cu n elemente și un număr k. Aflați al k-lea cel mai mare număr din vector.
    • Restricții:
      • $ 1 <= k <= n <= 10^5 $
      • Elementele vectorului au valori cuprinse între 0 și $ 10 ^ 9 $

Ca să înțelegem cum ne dorim să procedăm la PA, următoarea problemă este rezolvată. Soluțiile pentru această problemă se pot încărca pe platforma Leetcode.

Soluția 1

Soluția 1

Putem sorta vectorul crescător și să întoarcem al k-lea element de la finalul vectorului. Complexitate este de $ O(n log n) $.

Soluția 1 implementată în C++

Soluția 1 implementată în C++

class Solution {
 public:
   int findKthLargest(vector<int>& nums, int k) {
       std::sort(nums.begin(), nums.end());
       return nums[nums.size() - k];
   }
};

Soluția 1 implementată în Java

Soluția 1 implementată în Java

class Solution {
   public int findKthLargest(int[] nums, int k) {
        Arrays.sort(nums);
        return nums[nums.length - k];
   }
}

Soluția 2

Soluția 2

Pentru soluția precedentă, nu ne-am folosit de faptul că $ k < n $, deci s-ar putea obține ceva mai eficient. Trebuie să parcugem măcar o dată vectorul, deci mai puțin de $ O(n)$ nu putem obține. Fix n pași nu putem face, trebuie să îl folosim pe k. Deoarece ne trebuie al k-lea cel mai mare element, intuitiv ar trebui să ținem minte într-o structură de date cele mai mari k elemente din vector.

Ce structură alegem? Dorim să putem insera în ea și să ne zică maximul. Am fi tentați să folosim un max heap.

Când am adăuga un nou element, am dori să îl ștergem pe cel mai mic din structura de date. Prin urmare, am putea să folosim un min heap, în care ne propunem ca la orice moment stocăm cele mai mari k elemente din vector, parcurse până acum.

Astfel:

1. Se adaugă inițial primele k elemente în heap.

2. Pentru fiecare din elementele următoarele, dacă acesta este mai mare decât minimul din heap, se șterge minimul și se adaugă elementul curent. Mereu în heap avem k elemente la final de pas în această etapă.

3. Răspunsul este minimul din heap la finalul parcurgerii.

Complexitate este de $ O(n log k) $, care este mai bună. Implementați și testați pe Leetcode!

Soluția 3

Soluția 3

Hint: Soluția 2 nu este optimă! Se poate și $O(n)$, dar considerăm că este înafara scopului laboratorului 0.

pa/laboratoare/laborator-00.txt · Last modified: 2025/03/06 22:57 by darius.neatu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0