To jedna z najważniejszych technik projektowania algorytmów. Polega na trzech krokach: podziel problem na mniejsze podproblemy tego samego typu, rozwiąż je rekurencyjnie (aż do trywialnego przypadku bazowego), a następnie połącz wyniki cząstkowe w rozwiązanie całościowe. Ta technika często pozwala zejść ze złożoności O(n) do O(log n), albo z O(n²) do O(n log n).
Naiwne obliczenie aⁿ wymaga n mnożeń. Zauważmy jednak, że: jeśli n jest parzyste, aⁿ = (aⁿᐛ²)², a jeśli n jest nieparzyste, aⁿ = a × aⁿ⁻¹. Każde wywołanie zmniejsza wykładnik o połowę — stąd złożoność O(log n).
Klasyczny przykład "dziel i zwyciężaj": w posortowanej tablicy porównujemy szukaną wartość ze środkowym elementem i odrzucamy połowę tablicy w każdym kroku.
Naiwnie znalezienie min i max osobno wymaga 2n porównań. Metodą dziel i zwyciężaj można to zrobić w około 3n/2 porównań: dzielimy tablicę na połowy, rekurencyjnie znajdujemy (min, max) w każdej połowie, a następnie porównujemy wyniki cząstkowe (tylko 2 dodatkowe porównania na połączenie).
Napisz iteracyjną (bez rekurencji) wersję szybkiego potęgowania, korzystając z zapisu dwójkowego wykładnika n. Wskazówka: przechodzimy przez bity n od najmniej znaczącego, mnożąc wynik przez a za każdym razem, gdy bit jest równy 1, i podnosząc a do kwadratu w każdym kroku.
Zmodyfikuj funkcję min_max tak, aby zliczając globalną liczbę wykonanych porównań, potwierdzić empirycznie, że dla n=1000 elementowej tablicy liczba porównań jest bliska 3n/2, a nie 2n.
1. Jaka jest złożoność szybkiego potęgowania metodą dziel i zwyciężaj?
2. Ile w przybliżeniu porównań wymaga znalezienie min i max jednocześnie metodą dziel i zwyciężaj?
3. Który warunek kończy wyszukiwanie binarne z wynikiem „nie znaleziono”?