Overlapping Subproblems and Optimal Substructure in DSA Java - Time & Space Complexity
We want to understand how solving problems with overlapping parts affects the time it takes.
How does reusing solutions to smaller parts help reduce work?
Analyze the time complexity of the following Fibonacci calculation using simple recursion.
public int fib(int n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}
This code calculates the nth Fibonacci number by calling itself twice for smaller values.
Look at the repeated calls that happen again and again.
- Primary operation: Recursive calls to fib for n-1 and n-2.
- How many times: Many calls repeat the same fib values multiple times.
Each call splits into two more calls, doubling work roughly.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 177 calls |
| 20 | Over 21,000 calls |
| 30 | More than 2 million calls |
Pattern observation: The number of calls grows very fast, almost doubling each step.
Time Complexity: O(2^n)
This means the time needed grows exponentially as n increases, making it very slow for large n.
[X] Wrong: "Since fib calls fib(n-1) and fib(n-2), it should be about 2^n calls."
[OK] Correct: Each call creates two more calls, so calls multiply, not just add up.
Understanding overlapping subproblems helps you spot when to use smarter methods like memoization to save time.
What if we add a memory to store results already computed? How would the time complexity change?
Practice
overlapping subproblems property in dynamic programming?Solution
Step 1: Understand overlapping subproblems
Overlapping subproblems means the same smaller problems appear multiple times during solving.Step 2: Match with options
The problem can be broken into smaller subproblems that are solved multiple times. correctly states that subproblems repeat and are solved multiple times.Final Answer:
The problem can be broken into smaller subproblems that are solved multiple times. -> Option BQuick Check:
Overlapping subproblems = repeated smaller problems [OK]
- Confusing overlapping subproblems with unique subproblems
- Thinking sorting is required for overlapping subproblems
- Mixing greedy approach with dynamic programming
Solution
Step 1: Identify correct parameter types
Memoization requires storing results, so an int array for memo is needed. The input n should be int.Step 2: Check method signatures
public int fib(int n, int[] memo) uses int n and int[] memo, which is correct for memoized Fibonacci.Final Answer:
public int fib(int n, int[] memo) -> Option AQuick Check:
Memo array type matches input type [OK]
- Using void return type for Fibonacci function
- Using String type for numeric input or memo array
- Not passing memo array as parameter
public class FibMemo {
static int[] memo = new int[6];
public static int fib(int n) {
if (n <= 1) return n;
if (memo[n] != 0) return memo[n];
memo[n] = fib(n-1) + fib(n-2);
return memo[n];
}
public static void main(String[] args) {
System.out.println(fib(5));
}
}Solution
Step 1: Trace fib(5) calls with memoization
fib(5) calls fib(4) and fib(3), and so on. Memo stores results to avoid repeats.Step 2: Calculate fib(5)
fib(0)=0, fib(1)=1, fib(2)=1, fib(3)=2, fib(4)=3, fib(5)=5.Final Answer:
5 -> Option CQuick Check:
Fibonacci(5) = 5 [OK]
- Confusing fib(5) with fib(6)
- Ignoring memoization effect
- Expecting sum of all calls instead of fib(5)
public class Fib {
static int[] memo = new int[5];
public static int fib(int n) {
if (n <= 1) return n;
if (memo[n] != 0) return memo[n];
memo[n] = fib(n-1) + fib(n-2);
return memo[n];
}
public static void main(String[] args) {
System.out.println(fib(5));
}
}Solution
Step 1: Check memo array size and access
Memo array size is 5, so valid indices are 0 to 4. fib(5) tries to access memo[5], causing error.Step 2: Identify exception type
Accessing memo[5] causes ArrayIndexOutOfBoundsException at runtime.Final Answer:
ArrayIndexOutOfBoundsException due to memo size -> Option DQuick Check:
Array size < access index = error [OK]
- Assuming memo size is enough without checking
- Thinking recursion causes stack overflow here
- Ignoring runtime exceptions
Solution
Step 1: Understand minimum cost path problem
The problem breaks into smaller subproblems (cost to reach each cell) that overlap.Step 2: Check properties for dynamic programming
Optimal substructure means optimal solution uses optimal solutions of subproblems. Overlapping subproblems means subproblems repeat.Step 3: Match with options
The problem has overlapping subproblems and optimal substructure. correctly states both properties, justifying dynamic programming.Final Answer:
The problem has overlapping subproblems and optimal substructure. -> Option AQuick Check:
Overlapping subproblems + optimal substructure = DP [OK]
- Thinking sorting solves the problem
- Assuming greedy approach always works
- Ignoring overlapping subproblems
Ready to prove it?
Pass the test and this pattern moves unknown
