# Python | Implementing Dynamic programming using Dictionary

Dynamic Programming is one way which can be used as an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of subproblems so that we do not have to re-compute them when needed later. This simple optimization reduces time complexities from exponential to polynomial. In this article, a method to use dictionaries of python to implement dynamic programming has been discussed.

In order to understand the implementation of the dynamic programming in python, lets visualize it using the Fibonacci numbers problem.

In mathematical terms, the sequence of Fibonacci numbers is defined by the recurrence relation:

Fn = Fn-1 + Fn-2

with seed values:

F0 = 0 and F1 = 1

**Examples:**

Input:N = 9

Output:34

Explanation:

9^{th}number in the Fibonacci series is 34.

Input:N = 2

Output:1

Explanation:

2^{nd}number in the Fibonacci series is 1.

Below is the implementation of the naive approach:

`# Function to find nth Fibonacci number ` `def` `Fibonacci(n): ` ` ` ` ` `# Corner case ` ` ` `if` `n<` `0` `: ` ` ` `print` `(` `"Incorrect input"` `) ` ` ` ` ` `# Base case ` ` ` `elif` `n ` `=` `=` `0` `: ` ` ` `return` `0` ` ` `elif` `n ` `=` `=` `1` `: ` ` ` `return` `1` ` ` ` ` `# Recursive case ` ` ` `else` `: ` ` ` `return` `Fibonacci(n` `-` `1` `)` `+` `Fibonacci(n` `-` `2` `) ` ` ` `print` `(Fibonacci(` `9` `)) ` |

*chevron_right*

*filter_none*

**Output:**

34

Clearly, the above approach has exponential time complexity. In order to store the previously computed results, let us use the dictionary class of python.

**Approach:** The idea is to customize the *__missing__* method of the dictionary class. This method is executed when the user tries to access a key which is not in the dictionary. We will use our own function definition to rewrite this method.

Below is the implementation of the above approach:

`# Python program to customize the ` `# __missing__ method of the ` `# dictionary class in python ` ` ` `class` `Fibonacci(` `dict` `): ` ` ` ` ` `# Function signature of the ` ` ` `# __missing__ function in ` ` ` `# python ` ` ` `def` `__missing__(` `self` `, n): ` ` ` ` ` `# Base case ` ` ` `if` `n<` `=` `1` `: ` ` ` ` ` `# Storing the value in the ` ` ` `# dictionary before returning ` ` ` `self` `[n] ` `=` `n ` ` ` `return` `n ` ` ` ` ` `# Storing the value in the dictionary ` ` ` `# before returning the value ` ` ` `val ` `=` `self` `[n] ` `=` `self` `[n` `-` `1` `] ` `+` `self` `[n` `-` `2` `] ` ` ` `return` `val ` ` ` `if` `__name__ ` `=` `=` `"__main__"` `: ` ` ` ` ` `# Create an instance of the class ` ` ` `Fib ` `=` `Fibonacci() ` ` ` `N ` `=` `Fib[` `9` `] ` ` ` `print` `(N) ` |

*chevron_right*

*filter_none*

**Output:**

34

The above method can also be implemented by using a decorator in python.

Decorator is a very powerful and useful tool in python since it allows programmers to modify the behaviour of function or class. Decorators allow us to wrap another function in order to extend the behaviour of the wrapped function, without permanently modifying it. Here, memoization is used to implement a decorator.

Below is the implementation of the above approach:

`# Python program to find the nth Fibonacci ` `# number with memoization using decorators ` ` ` `from` `inspect ` `import` `signature ` ` ` `# Defining a decorator ` `class` `memoise(` `dict` `): ` ` ` ` ` `# Initializing function ` ` ` `def` `__init__(` `self` `, func): ` ` ` `self` `.func ` `=` `func ` ` ` `self` `.signature ` `=` `signature(func) ` ` ` ` ` `# Missing method to store the ` ` ` `# Fibonacci numbers in a ` ` ` `# Dictionary ` ` ` `def` `__missing__(` `self` `, key): ` ` ` `(arg, kwarg) ` `=` `key ` ` ` `self` `[key] ` `=` `val ` `=` `self` `.func(` `*` `arg, ` ` ` `*` `*` `dict` `(kwarg)) ` ` ` `return` `val ` ` ` ` ` `def` `__call__(` `self` `, ` `*` `arg, ` `*` `*` `kwarg): ` ` ` `key ` `=` `self` `.signature.bind(` `*` `arg, ` ` ` `*` `*` `kwarg) ` ` ` `return` `self` `[key.args, ` ` ` `frozenset` `(key.kwargs.items())] ` ` ` ` ` `# Function to find the n-th Fibonacci ` `# number using the above defined ` `# decorator ` `@memoise` `def` `Fibonacci(n): ` ` ` ` ` `# Corner case ` ` ` `if` `n<` `0` `: ` ` ` `print` `(` `"Incorrect input"` `) ` ` ` ` ` `# Base cases ` ` ` `elif` `n ` `=` `=` `0` `: ` ` ` `return` `0` ` ` `elif` `n ` `=` `=` `1` `: ` ` ` `return` `1` ` ` ` ` `# Recursive case ` ` ` `else` `: ` ` ` `return` `Fibonacci(n` `-` `1` `)` `+` `Fibonacci(n` `-` `2` `) ` ` ` `if` `__name__ ` `=` `=` `"__main__"` `: ` ` ` `print` `(Fibonacci(` `9` `)) ` |

*chevron_right*

*filter_none*

**Output:**

34

GeeksforGeeks has prepared a complete interview preparation course with premium videos, theory, practice problems, TA support and many more features. Please refer Placement 100 for details

## Recommended Posts:

- Dynamic Programming on Trees | Set 2
- Bitmasking and Dynamic Programming | Set-2 (TSP)
- Dynamic Programming on Trees | Set-1
- Dynamic Programming | Building Bridges
- Dynamic Programming vs Divide-and-Conquer
- Greedy approach vs Dynamic programming
- Ackermann's function using Dynamic programming
- Double Knapsack | Dynamic Programming
- How to solve a Dynamic Programming Problem ?
- Top 20 Dynamic Programming Interview Questions
- Convert N to M with given operations using dynamic programming
- Number of Unique BST with a given key | Dynamic Programming
- Longest subsequence with a given OR value : Dynamic Programming Approach
- Optimal Substructure Property in Dynamic Programming | DP-2
- Overlapping Subproblems Property in Dynamic Programming | DP-1

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.