Memoizacja

Python SELF PL
Poziom 57 , Lekcja 3
Dostępny

4.1 Definicja memoizacji i jej podstawowe koncepcje

Memoizacja — to technika optymalizacji, w której wyniki kosztownych funkcji są przechowywane, aby mogły być ponownie wykorzystane przy kolejnych wywołaniach z tymi samymi argumentami. To zmniejsza liczbę ponownych obliczeń, tym samym zwiększając wydajność.

Podstawowe koncepcje:

1. Caching:

Przechowywanie wyników funkcji w jakiejś strukturze danych (na przykład w słowniku lub tablicy), aby przy kolejnych wywołaniach z tymi samymi argumentami zwrócić już zapisany wynik, zamiast go ponownie obliczać.

2. Tabela wyszukiwania (Lookup Table):

Struktura danych używana do przechowywania wyników wcześniejszych wywołań funkcji. Może to być hash table (słownik) lub tablica.

3. Wywołania rekurencyjne:

Memoizacja jest szczególnie użyteczna dla funkcji rekurencyjnych, gdzie te same podzadania mogą być wykonywane kilka razy z tymi samymi parametrami.

Złożoność czasowa i przestrzenna zoptymalizowanych algorytmów:

Złożoność czasowa:

Dla wielu rekurencyjnych zadań memoizacja zmniejsza złożoność czasową poprzez zmniejszenie liczby powtarzających się obliczeń. Na przykład, rekurencyjne obliczenie liczb Fibonacciego ma złożoność czasową O(2^n), a z memoizacją — O(n).

Złożoność przestrzenna:

Złożoność przestrzenna zwiększa się poprzez przechowywanie wyników w cache. Zwykle to O(n) dla zadania wymagającego memoizacji.

Podsumowanie:

Memoizacja — to potężna technika optymalizacji rekurencyjnych algorytmów, pozwalająca znacznie poprawić ich wydajność poprzez zmniejszenie liczby powtarzających się obliczeń.

Jest szczególnie użyteczna dla zadań, w których te same podzadania są wykonywane wielokrotnie z tymi samymi parametrami. Zrozumienie koncepcji memoizacji i jej zastosowanie w praktyce pozwala efektywnie rozwiązywać zadania z dużym obciążeniem obliczeniowym.

4.2 Przykłady optymalizacji

Przykłady optymalizacji rekurencyjnych algorytmów z użyciem memoizacji

Przykład 1: Liczby Fibonacciego

Rekurencyjny algorytm obliczania liczb Fibonacciego bez memoizacji ma wykładniczą złożoność czasową. Użycie memoizacji znacznie poprawia wydajność.


def fibonacci(n, memo=None):
    if memo is None:
        memo = {}
    if n in memo:
        return memo[n]
    if n <= 1:
        return n
    memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo)
    return memo[n]
        
# Przykład użycia:
print(fibonacci(10))  # Wynik: 55
        

Ważne! Zwróć uwagę, że używamy memo=None jako wartości domyślnej, a następnie tworzymy pusty słownik wewnątrz funkcji, jeśli memo nie jest przekazany. To pozwala uniknąć problemu z modyfikowalnym obiektem jako wartością domyślną.

Przykład 2: Suma podzbiorów

Trzeba określić, czy istnieje podzbiór danego zbioru, suma elementów którego jest równa danej wartości.


def is_subset_sum(arr, n, sum_value, memo=None):
    if memo is None:
        memo = {}
    if (n, sum_value) in memo:
        return memo[(n, sum_value)]
    if sum_value == 0:
        return True
    if n == 0 and sum_value != 0:
        return False
    if arr[n - 1] > sum_value:
        memo[(n, sum_value)] = is_subset_sum(arr, n - 1, sum_value, memo)
        return memo[(n, sum_value)]
    memo[(n, sum_value)] = is_subset_sum(arr, n - 1, sum_value, memo) or is_subset_sum(arr, n - 1, sum_value - arr[n - 1], memo)
    return memo[(n, sum_value)]
        
# Przykład użycia:
arr = [3, 34, 4, 12, 5, 2]
sum_value = 9
n = len(arr)
print(is_subset_sum(arr, n, sum_value))  # Wynik: True
        

Memoizacja — to w zasadzie caching wyników podzadań.

Na przykład, liczba Fibonacciego F(10) == F(9) + F(8), ale aby obliczyć F(9), musimy obliczyć F(8) i F(7). Czyli F(8) musielibyśmy obliczyć dwa razy: jako pierwsze składnik do F(9) i jako drugi składnik do F(10). Aby nie obliczać go dwa razy, musimy go zapisać po pierwszym obliczeniu.

1
Опрос
Rekurencja,  57 уровень,  3 лекция
недоступен
Rekurencja
Rekurencja
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION