🧠
💾 Informatyka Algorytmika i programowanie PR

Algorytmy zaawansowane

Rekurencja, dziel-i-zwyciężaj, programowanie dynamiczne, algorytmy zachłanne i metoda połowienia — rdzeń egzaminu z informatyki, ~30% wszystkich punktów.

300
zadań w dziale
8-14 pkt
średnio na maturze
10
umiejętności
8
pułapek do unikania
LIVE — pytania z bazy dla tego tematu

Wypróbuj pytania z tematu „Algorytmy zaawansowane"

Trzy losowe pytania z bazy — analiza kodu, algorytmy, SQL.

Algorytmy zaawansowane to absolutny rdzeń egzaminu maturalnego z informatyki — pojawiają się w KAŻDYM arkuszu i są warte najwięcej punktów. CKE konsekwentnie sprawdza umiejętność stosowania rekurencji (procedury sortowania, parsery wyrażeń), programowania dynamicznego (najdłuższy podciąg rosnący, segment o największej sumie, łańcuchy przedziałów), metody dziel-i-zwyciężaj (sortowanie szybkie, wyszukiwanie połówkowe) oraz strategii zachłannej (problem plecakowy w wersji ciągłej, harmonogramowanie zadań). Najczęstsze typy zadań to: zapisanie nierekurencyjnej wersji procedury rekurencyjnej (4-5 pkt), znalezienie segmentu/podciągu o zadanych własnościach (3-4 pkt), analiza złożoności podanego algorytmu oraz porównanie dwóch wariantów. Kluczem jest umiejętność rozumienia pseudokodu i przekładania go na C++/Python (lub odwrotnie) oraz świadome dobranie struktury danych do problemu — tablicy zwykłej, stosu, kolejki, listy dynamicznej.

Co znajdziesz w tym dziale

Filtruj zadania po typie (kod, SQL, pseudokod, ABCD), trudności i pochodzeniu — wszystko widoczne przed rozpoczęciem.

Typy zadań

CLOSED 75
OPEN 44
CALCULATION 36
FILL_IN 33
TABLE_DATA 28
P/F 27
Dobieranie 25
GRAPH_INTERPRET 16
MULTI_SELECT 16

Poziom trudności

Łatwe 39 (13%)
Średnie 163 (54%)
Trudne 84 (28%)
Bardzo trudne 14 (5%)

📚 Źródła zadań

PR 300
🎯 CO MUSISZ UMIEĆ

Umiejętności sprawdzane w tym dziale

Lista zgodna z wymaganiami podstawy programowej PR i Informatorem CKE.

1

Rekurencja — schemat i baza

Identyfikacja przypadku bazowego (warunek stopu) oraz kroku rekurencyjnego (wywołanie z mniejszymi danymi). Klasyczne przykłady: silnia, Fibonacci, NWD Euklidesa, wieże Hanoi, sortowanie przez wstawianie rekurencyjnie. Świadomość kosztu pamięci (stos wywołań).

2

Eliminacja rekurencji — wersja iteracyjna

Przekształcanie procedury rekurencyjnej w wersję pętlową przy użyciu stosu lub akumulatora. To częste polecenie maturalne (4-5 pkt). Wzorzec: identyfikuj parametry zmienne, zastąp wywołanie pętlą while/for, kontroluj warunek zakończenia.

3

Programowanie dynamiczne — tablica wyników częściowych

Klasyczne problemy: maksymalny segment (Kadane O(n)), najdłuższy podciąg rosnący O(n²) lub O(n log n), najdłuższy wspólny podciąg, problem plecakowy 0-1, łańcuchy przedziałów. Kluczowa idea: wynik[i] zależy od wynik[<i], unikamy ponownego liczenia.

4

Algorytm Kadane — segment o największej sumie

Liniowe O(n) rozwiązanie: utrzymuj sumę bieżącą; jeśli zejdzie poniżej 0 — zacznij od nowa. Pamiętaj o wariantach: segment niepusty, najdłuższy taki segment, segment o sumie ≤ K, dwuwymiarowy odpowiednik na macierzy.

5

Metoda dziel-i-zwyciężaj

Podział problemu na ~równe podproblemy, rekurencyjne rozwiązanie, scalenie wyników. Sortowanie przez scalanie O(n log n), sortowanie szybkie (quicksort) ze średnim O(n log n), wyszukiwanie połówkowe O(log n), potęgowanie szybkie O(log n).

6

Algorytmy zachłanne (greedy)

Wybór lokalnie najlepszej opcji w każdym kroku. Działa, gdy problem ma własność wyboru zachłannego. Klasyka: wydawanie reszty (dla "porządnych" nominałów), problem plecakowy ciągły (ułamkowy), harmonogramowanie zadań — sortowanie po czasie zakończenia.

7

Wyszukiwanie połówkowe (bisection)

Tablica MUSI być posortowana. Algorytm: lewy=0, prawy=n-1; dopóki lewy ≤ prawy: środek = (l+p)/2, porównaj z szukaną wartością i zawęź przedział. Złożoność O(log n). Wariant: znajdź pierwsze/ostatnie wystąpienie, znajdź najmniejszy element ≥ x.

8

Analiza złożoności obliczeniowej

Notacja O(): O(1) — stała, O(log n) — logarytmiczna, O(n) — liniowa, O(n log n) — quasi-liniowa, O(n²) — kwadratowa, O(n³) — sześcienna, O(2ⁿ) — wykładnicza. Świadomość, że trzy zagnieżdżone pętle = O(n³) (nie do zaakceptowania dla n=10⁵).

9

Operacje arytmetyczne w pseudokodzie

Operacje dozwolone w zadaniach "kartka": +, -, *, /, div (dzielenie całkowite), mod (reszta), porównania, instrukcje sterujące. ZABRONIONE: funkcje biblioteczne typu sort(), reverse(), str.upper(), Math.pow(). Musisz wszystko zaimplementować ręcznie.

10

Łańcuchy przedziałów i porządki

Dla zbioru przedziałów [a,b] — znajdź najdłuższy łańcuch zagnieżdżeń. Wzorzec: posortuj przedziały po długości rosnąco; dla każdego przedziału licz dl[i] = max(dl[j])+1 po wszystkich j zawartych w i. Analogiczne do najdłuższego podciągu rosnącego — O(n²).

⚠️ TYPOWE BŁĘDY

Pułapki, w które wpadają maturzyści

Najczęstsze błędy obserwowane przez CKE — i jak ich unikać.

Błąd

Rekurencja bez warunku stopu lub z błędnym warunkiem.

Poprawnie

ZAWSZE sprawdź najpierw warunek bazowy, dopiero potem rób wywołanie rekurencyjne. Wzorzec: "jeśli n ≤ 0 zwróć ...; w przeciwnym razie zwróć f(n-1) + ...".

💡 Dlaczego: Klasyczny powód błędu Stack Overflow. Na maturze nawet jedna zła linia odejmuje 2-3 punkty. Zawsze pisz przypadek bazowy JAKO PIERWSZY.
Błąd

Trzy zagnieżdżone pętle dla zadania z n=100000.

Poprawnie

Sprawdź rozmiar danych! Dla n=100000 musisz mieć co najwyżej O(n²) ale lepiej O(n log n) lub O(n). Użyj Kadane, programowania dynamicznego, sortowania + przejścia.

💡 Dlaczego: CKE celowo daje zadania w dwóch wariantach: n=1000 (sześcienne przejdzie) i n=100000 (sześcienne timeout). Identyfikuj wariant w treści zadania.
Błąd

Dla najdłuższego podciągu rosnącego (LIS) używanie warunku t[j] ≤ t[i].

Poprawnie

Dla podciągu ROSNĄCEGO: t[j] < t[i] (ściśle). Dla NIEMALEJĄCEGO: t[j] ≤ t[i].

💡 Dlaczego: Kluczowa różnica w treści zadania. Jedno słowo w treści = inny wynik. "Rosnący" oznacza ściśle, "niemalejący" oznacza słabo. Zawsze przeczytaj polecenie 2 razy.
Błąd

Algorytm zachłanny zastosowany do problemu plecakowego 0-1.

Poprawnie

Greedy działa tylko dla problemu plecakowego CIĄGŁEGO (możemy brać ułamki). Dla 0-1 (przedmiot bierzemy w całości lub wcale) — programowanie dynamiczne.

💡 Dlaczego: Zachłanny sortuje po wartości/wadze i bierze najlepsze; dla 0-1 może to dać wynik gorszy od optymalnego. PD daje optymalny w O(n·W).
Błąd

Bisection na tablicy nieposortowanej.

Poprawnie

Wyszukiwanie połówkowe DZIAŁA tylko na danych posortowanych. Jeśli nie są — najpierw posortuj O(n log n), potem szukaj O(log n).

💡 Dlaczego: Częsta pułapka: zadanie daje "tablicę liczb" — student od razu robi bisection. CKE celowo testuje, czy student pamięta o tym warunku.
Błąd

Implementacja Kadane bez obsługi tablicy z wszystkimi liczbami ujemnymi.

Poprawnie

Inicjalizuj maks = t[0] (NIE maks = 0!) i ost_suma = t[0]. Dzięki temu jeśli wszystkie liczby są ujemne, algorytm zwróci największą (najmniej ujemną).

💡 Dlaczego: Klasyczny błąd graniczny. Maks = 0 daje wynik 0 dla tablicy [-5,-3,-1], a poprawny segment niepusty to [-1].
Błąd

Próba zapisania funkcji rekurencyjnej z parametrem licznika "ile wywołań".

Poprawnie

Licznik wywołań zwykle utrzymuj jako zmienną GLOBALNĄ albo PRZEKAZUJ przez referencję/wskaźnik. Inaczej każde wywołanie zaczyna od 0.

💡 Dlaczego: Pomieszanie semantyki rekurencji. CKE nie wymaga implementacji licznika, ale studenci sami sobie utrudniają — używaj zmiennej globalnej, jeśli język na to pozwala.
Błąd

Programowanie dynamiczne bez sortowania danych wejściowych.

Poprawnie

Dla łańcuchów przedziałów / problemów z zawieraniem — PIERWSZY KROK to sortowanie (po długości, po końcu, po początku). Dopiero potem buduj tablicę dl[].

💡 Dlaczego: Bez sortowania PD nie ma porządku, w którym można obliczać kolejne komórki tablicy. Wynik będzie błędny.
🧠 DO ZAPAMIĘTANIA

Definicje, wzory i pojęcia kluczowe

Spaced Repetition przypomina te pojęcia i wzorce algorytmiczne dokładnie wtedy, kiedy zaczynasz je zapominać.

Rekurencja

Technika, w której funkcja wywołuje samą siebie z mniejszymi/prostszymi argumentami, aż osiągnie przypadek bazowy.

silnia(n) = jeśli n≤1 zwróć 1; w przeciwnym razie zwróć n * silnia(n-1)

Programowanie dynamiczne (PD)

Strategia, w której zapamiętujemy wyniki podproblemów w tablicy/słowniku, aby unikać ponownego obliczania.

fib[i] = fib[i-1] + fib[i-2], buduj od fib[0]=fib[1]=1

Algorytm Kadane

Liniowy O(n) algorytm znajdowania spójnego podciągu o największej sumie.

ost = max(t[i], ost+t[i]); maks = max(maks, ost)

Najdłuższy podciąg rosnący (LIS)

Problem znalezienia najdłuższego (niekoniecznie spójnego) podciągu ściśle rosnącego.

O(n²) z dl[i]=max(dl[j])+1 dla j<i z t[j]<t[i]

Dziel-i-zwyciężaj

Strategia: dziel problem na ~równe części, rozwiąż rekurencyjnie, scal wyniki.

Merge sort, quicksort, binary search, potęgowanie szybkie

Algorytm zachłanny (greedy)

Strategia: w każdym kroku wybieraj lokalnie najlepszą opcję.

Działa dla: harmonogramowanie, plecakowy ciągły, Huffman, MST

Wyszukiwanie połówkowe

Algorytm O(log n) szukania elementu w POSORTOWANEJ tablicy.

l=0, p=n-1; dopóki l≤p: m=(l+p)/2, porównaj t[m] z x

Złożoność O()

Asymptotyczne oszacowanie liczby operacji w funkcji rozmiaru danych n.

O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(2ⁿ)

Przypadek bazowy

Najprostszy przypadek w rekurencji, dla którego znamy odpowiedź bez dalszych wywołań.

Bez niego = nieskończona rekursja = Stack Overflow

Stos wywołań

Struktura pamięci przechowująca aktywne wywołania funkcji. Każda rekurencja zużywa stos.

Głębokość rekurencji > 10⁵ często powoduje przepełnienie

Mémoization

Wariant PD: pamiętamy wyniki funkcji rekurencyjnej w słowniku/tablicy i nie liczymy dwukrotnie.

Top-down PD vs bottom-up PD

Łańcuch przedziałów

Ciąg przedziałów P₁, P₂, ..., Pₖ taki, że każdy następny zawiera poprzedni.

Znajdowane przez sortowanie + PD analogiczne do LIS

🧭 STRATEGIA NAUKI

Jak skutecznie uczyć się tego działu

1

Czytaj polecenie 2-3 razy. CKE celowo używa precyzyjnych słów: "rosnący" ≠ "niemalejący", "spójny podciąg" ≠ "podciąg", "ściśle większy" ≠ "większy lub równy". Każde słowo zmienia algorytm.

2

Sprawdź rozmiar danych PRZED napisaniem kodu. n=100 → możesz O(n³). n=10000 → max O(n²). n=10⁵ → musisz O(n log n) lub O(n). To determinuje wybór algorytmu.

3

Zawsze napisz przypadek bazowy rekurencji JAKO PIERWSZY. Potem dopisuj krok rekurencyjny. Po napisaniu — przetestuj na ręcznie obliczonym przykładzie z polecenia.

4

Dla zadań z plikiem dane.txt: najpierw policz ręcznie wynik dla przykładu z polecenia (1-2 wiersze). Dopiero potem skaluj na cały plik. Jeśli twój kod nie daje dobrego wyniku dla przykładu — nie ma sensu uruchamiać na 100000 elementach.

5

Ucz się 4 wzorców programowania dynamicznego: (1) maksymalny segment Kadane, (2) najdłuższy podciąg rosnący LIS, (3) najdłuższy wspólny podciąg LCS, (4) problem plecakowy 0-1. To 80% zadań PD na maturze.

6

Pseudokod CKE używa: dla i od a do b wykonaj / dopóki / jeśli ... w przeciwnym razie / ← (przypisanie) / div, mod (operacje całkowite). Naucz się tej składni — w zadaniach "kartka" musisz pisać w niej, nie w C++.

7

Algorytm w pseudokodzie zawsze testuj na przykładzie z polecenia ręcznie (krok po kroku, prowadząc kolumny stanu zmiennych). Często wykrywasz off-by-one, zły warunek pętli czy złą inicjalizację.

Typy zadań w tym dziale

Każdy typ wymaga innej strategii rozwiązywania.

📋 Pseudokod 💻 Kod 🔍 Analiza Otwarte

FAQ — Algorytmy zaawansowane

Najczęstsze pytania o ten dział

Czy mogę użyć C++, Pythona czy musi być pseudokod?
W zadaniach praktycznych (z plikiem dane.txt, gdzie oddajesz kod programu) — wybierasz dowolny język spośród dostępnych na stanowisku komputerowym: zwykle C++, Python, Java, Pascal. W zadaniach "kartka" (oznaczone symbolem kartki) — pseudokod lub język programowania. Pseudokod jest często bezpieczniejszy, bo nie musisz pamiętać szczegółów składniowych.
Czy mogę używać bibliotek typu sort() w Pythonie albo std::sort w C++?
W zadaniach praktycznych — TAK, możesz używać wszystkiego, co daje twój język. W zadaniach "kartka" lub gdy polecenie wyraźnie mówi "nie używaj funkcji wbudowanych" — musisz zaimplementować sortowanie ręcznie. Czytaj polecenie uważnie. Typowe ograniczenie: "możesz wykorzystać tylko operacje arytmetyczne, instrukcje sterujące i porównania".
Czemu mój algorytm O(n³) daje dobry wynik dla n=1000, ale timeout dla n=100000?
n³ dla n=1000 to 10⁹ operacji — to ok. 5-10 sekund w C++, granica akceptowalności na egzaminie. Dla n=100000 to 10¹⁵ — kompletnie poza zasięgiem. CKE celowo daje warianty zadania z różnym n żeby sprawdzić, czy znasz Kadane (O(n)) zamiast naiwnego O(n³). Jeśli widzisz n≥10⁵ — szukaj algorytmu liniowego.
Kiedy algorytm zachłanny daje poprawny wynik, a kiedy nie?
Zachłanny działa, gdy problem ma "własność wyboru zachłannego" — lokalnie optymalna decyzja prowadzi do globalnie optymalnej. Działa dla: wydawania reszty (gdy nominały są "porządne" jak 1,2,5,10,20,50,100), harmonogramowania (sortuj po czasie zakończenia), MST (algorytmy Kruskala/Prima), Huffmana. NIE działa dla: problem plecakowy 0-1 (potrzeba PD), TSP (potrzeba dokładne lub heurystyki).
Jak zacząć rozwiązywanie zadania algorytmicznego na maturze?
Trzy kroki: (1) PRZECZYTAJ polecenie 2 razy, podkreśl wartości n, ograniczenia, dokładne zwroty ("spójny", "rosnący", "różnych"). (2) ROZWIĄŻ ręcznie przykład z polecenia — to weryfikacja zrozumienia. (3) DOBIERZ algorytm w oparciu o rozmiar danych: n≤100 — brute force; n≤10000 — O(n²); n≥10⁵ — O(n log n) lub O(n). Dopiero potem koduj.

Powiązane działy

Naturalne kontynuacje tematu

🧠

Zacznij rozwiązywać zadania z algorytmy zaawansowane

Pełen dostęp do 300 zadań z tego działu (PR), edytora kodu C++/Python/Java, klienta SQL, oceny AI z punktacją CKE, Spaced Repetition wzorców algorytmicznych.

Od 49 zł / miesiąc. Anulujesz kiedy chcesz.

Rozpocznij ćwiczenie