Skip to content

Commit 268059c

Browse files
committed
docs: document memoisation strategies for recursive optimizations
- Detail the transition from exponential O(2^n) to linear O(n) complexity - Explain the use of state-tracking tuples in the making_change algorithm - Summarize the space-vs-time trade-offs applied to Fibonacci and Coin Change - Document the refactoring into helper/wrapper patterns
1 parent 5d3c4ad commit 268059c

1 file changed

Lines changed: 26 additions & 0 deletions

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Changes Made: Optimization via Memoisation
2+
3+
## Overview
4+
The goal of these changes was to improve the performance of recursive functions that were previously performing redundant calculations. By introducing a manual cache (memoisation), the time complexity was reduced from exponential to linear.
5+
6+
## 1. Fibonacci Optimization (`fibonacci.py`)
7+
- **Implemented Memoisation**: Introduced a dictionary named `memo` to store the results of each Fibonacci term as it is calculated.
8+
- **Improved Complexity**:
9+
- **Before**: $O(2^n)$ (Exponential) - The function recalculated the same branches of the recursion tree millions of times.
10+
- **After**: $O(n)$ (Linear) - Each term is calculated exactly once and then retrieved from the cache.
11+
- **Readability**: Renamed the parameter `n` to `term_index` to more clearly describe that the function is looking for a specific position in a sequence.
12+
13+
## 2. Making Change Optimization (`making_change.py`)
14+
- **Recursive Helper Pattern**: Refactored the original iterative-recursive logic into a dedicated helper function (`ways_to_make_change_helper`) to better support memoisation.
15+
- **State Tracking**:
16+
- Created a **state key** using a Tuple: `(total, len(coins))`.
17+
- **The "Why"**: A unique solution depends on both the amount of money left and which coins are still available. A tuple is used because it is immutable and can be used as a dictionary key.
18+
- **Logic Refinement**:
19+
- Updated the base case to return `1` when `total == 0`, representing a successful combination.
20+
- Added `memo.clear()` in the wrapper function to ensure the cache is fresh for every new call to the main function.
21+
- **Legacy Preservation**: Maintained original variable names (`coin`, `count_of_coin`, `intermediate`) while implementing the performance improvements.
22+
23+
## 3. Technical Trade-offs: Space vs. Time
24+
In both implementations, I applied the **Space-vs-Time trade-off**:
25+
- **The Cost (Space)**: Increased memory usage to store the `memo` dictionary.
26+
- **The Benefit (Time)**: Drastic reduction in execution time. For example, `ways_to_make_change(9176)` now returns a result instantly, whereas the unoptimised version would likely never finish on standard hardware.

0 commit comments

Comments
 (0)