💡 The first player can secure a positive score difference, meaning a win.
reconstruct
Read final answer from dp[0][3]
Check if dp[0][3] > 0 to determine if the first player wins.
💡 A positive dp[0][3] means the first player can guarantee a win.
Line:return dp[0][n-1] > 0
💡 The first player (Alex) can win with optimal play on this input.
def stoneGame(piles):
n = len(piles) # STEP 1
dp = [[0]*n for _ in range(n)] # STEP 1
for i in range(n): # STEP 2
dp[i][i] = piles[i] # STEP 2
for length in range(2, n+1): # STEP 3
for i in range(n - length + 1): # STEP 4-11
j = i + length - 1
dp[i][j] = max(piles[i] - dp[i+1][j], piles[j] - dp[i][j-1]) # STEP 4-11
return dp[0][n-1] > 0 # STEP 12
if __name__ == '__main__':
print(stoneGame([5,3,4,5])) # True
📊
Stone Game (Optimal Strategy) - Watch the Algorithm Execute, Step by Step
Watching the dp table fill step-by-step reveals how the algorithm builds solutions for bigger intervals from smaller ones, making the optimal strategy clear.
Step 1/12
·Active fill★Answer cell
Initializing dp array
i\w
0
1
2
3
i=0
0
?
?
?
i=1
?
0
?
?
i=2
?
?
0
?
i=3
?
?
?
0
unfilled
Initializing dp array
i\w
0
1
2
3
i=0
5
?
?
?
i=1
?
3
?
?
i=2
?
?
4
?
i=3
?
?
?
5
dp[0][0] = 5
Initializing dp array
i\w
0
1
2
3
i=0
5
?
?
?
i=1
?
3
?
?
i=2
?
?
4
?
i=3
?
?
?
5
waiting
Item 0 - wt:5 val:2
i\w
0
1
2
3
i=0
5
2
?
?
i=1
?
3
?
?
i=2
?
?
4
?
i=3
?
?
?
5
dp[0][1] = max(5-3,3-5) = 2
Item 1 - wt:3 val:1
i\w
0
1
2
3
i=0
5
2
?
?
i=1
?
3
1
?
i=2
?
?
4
?
i=3
?
?
?
5
dp[1][2] = max(3-4,4-3) = 1
Item 2 - wt:4 val:1
i\w
0
1
2
3
i=0
5
2
?
?
i=1
?
3
1
?
i=2
?
?
4
1
i=3
?
?
?
5
dp[2][3] = max(4-5,5-4) = 1
Initializing dp array
i\w
0
1
2
3
i=0
5
2
?
?
i=1
?
3
1
?
i=2
?
?
4
1
i=3
?
?
?
5
waiting
Item 0 - wt:5 val:4
i\w
0
1
2
3
i=0
5
2
4
?
i=1
?
3
1
?
i=2
?
?
4
1
i=3
?
?
?
5
dp[0][2] = max(5-1,4-2) = 4
Item 1 - wt:3 val:4
i\w
0
1
2
3
i=0
5
2
4
?
i=1
?
3
1
4
i=2
?
?
4
1
i=3
?
?
?
5
dp[1][3] = max(3-1,5-1) = 4
Initializing dp array
i\w
0
1
2
3
i=0
5
2
4
?
i=1
?
3
1
4
i=2
?
?
4
1
i=3
?
?
?
5
waiting
Item 0 - wt:5 val:1
i\w
0
1
2
3
i=0
5
2
4
1
i=1
?
3
1
4
i=2
?
?
4
1
i=3
?
?
?
5
dp[0][3] = max(5-4,5-4) = 1
Item 0 - wt:5 val:1
i\w
0
1
2
3
i=0
5
2
4
1
i=1
?
3
1
4
i=2
?
?
4
1
i=3
?
?
?
5
Answer cell dp[0][3] = 1 > 0
Key Takeaways
✓ The dp table stores the maximum score difference the current player can achieve over the opponent for every interval.
This insight is hard to see from code alone because the dp values represent differences, not absolute scores.
✓ The table is filled from smaller intervals to larger intervals, ensuring dependencies are resolved before use.
Seeing the fill order visually clarifies why the algorithm uses bottom-up tabulation.
✓ At each interval, the choice to pick the left or right pile depends on maximizing the difference after the opponent's optimal response.
Watching the max decision at each cell shows how the algorithm simulates optimal play.
Practice
(1/5)
1. You are given an n x n integer matrix. You want to find a path from the top row to the bottom row such that you move one step down each time, and at each step you can move to the same column, the column to the left, or the column to the right. The goal is to minimize the sum of the values along this path. Which algorithmic approach guarantees finding the minimum sum efficiently?
easy
A. Greedy algorithm that picks the minimum adjacent value at each step
B. Sorting each row and picking the smallest values independently
C. Depth-first search exploring all paths without memoization
D. Dynamic programming that builds solutions row by row using previous row results
Solution
Step 1: Understand the problem constraints
The problem requires considering all possible paths moving down and diagonally, which suggests overlapping subproblems and optimal substructure.
Step 2: Identify the suitable algorithm
Dynamic programming fits because it efficiently computes minimum sums for each cell based on the previous row's results, avoiding redundant calculations.
Final Answer:
Option D -> Option D
Quick Check:
Greedy and sorting fail to consider future steps; DFS without memoization is exponential [OK]
Hint: DP uses previous row results to build solutions [OK]
Common Mistakes:
Thinking greedy or sorting per row suffices
Ignoring overlapping subproblems
2. You are given a printer that can print a continuous substring of identical characters in one turn. Given a string, you want to find the minimum number of turns needed to print the entire string. Which algorithmic approach guarantees an optimal solution for this problem?
easy
A. Dynamic Programming over intervals with string compression and merging states
B. Greedy approach printing each character separately from left to right
C. Simple recursion without memoization or compression
D. Sliding window technique to find longest repeated substrings
Solution
Step 1: Understand problem constraints
The problem requires minimizing turns to print a string where each turn prints a continuous block of identical characters.
Step 2: Identify suitable algorithmic pattern
Greedy or sliding window approaches fail to merge overlapping prints optimally. Pure recursion is inefficient. Interval DP with string compression and merging states captures overlapping subproblems and optimizes turns.
Final Answer:
Option A -> Option A
Quick Check:
Interval DP with compression is known optimal [OK]
Hint: Interval DP with compression merges overlapping prints [OK]
Common Mistakes:
Assuming greedy printing each char separately is optimal
3. Consider the following buggy code for finding the cheapest flight within K stops. Which line contains the subtle bug that causes incorrect results on some inputs?
def findCheapestPrice(n, flights, src, dst, K):
INF = float('inf')
prev = [INF] * n
prev[src] = 0
for _ in range(K + 1):
for u, v, w in flights:
if prev[u] != INF:
prev[v] = min(prev[v], prev[u] + w)
return prev[dst] if prev[dst] != INF else -1
medium
A. Line 4: Initializing prev[src] = 0
B. Line 7: Checking if prev[u] != INF before relaxing edges
C. Line 6: Using prev array directly inside the loop instead of a separate curr array
D. Line 9: Returning -1 if prev[dst] is INF
Solution
Step 1: Understand the DP update mechanism
In bottom-up DP, updates for the current iteration must not affect other relaxations in the same iteration, so a separate curr array is needed.
Step 2: Identify the bug
Using prev directly causes updated costs to be used immediately in the same iteration, leading to incorrect minimum costs.
Final Answer:
Option C -> Option C
Quick Check:
Separate curr array prevents premature updates [OK]
Hint: Must use separate curr array to avoid premature updates [OK]
Common Mistakes:
Updating prev in-place during iteration
Forgetting to copy arrays
Ignoring stop constraints
4. What is the time and space complexity of the optimal space-optimized bottom-up DP solution for the Unique Paths II problem on an m x n grid with obstacles?
medium
A. Time: O(m*n), Space: O(m*n)
B. Time: O(m+n), Space: O(m+n)
C. Time: O(m*n), Space: O(n)
D. Time: O(2^(m+n)), Space: O(m*n)
Solution
Step 1: Analyze time complexity
The algorithm iterates over each cell once in nested loops: O(m*n).
Step 2: Analyze space complexity
Uses a single 1D dp array of length n, so space is O(n).
Final Answer:
Option C -> Option C
Quick Check:
Nested loops over m and n, dp array size n [OK]
Hint: Nested loops over m and n, dp array size n [OK]
Common Mistakes:
Confusing recursion stack space with dp array
Assuming full 2D dp array used
Mistaking linear time for exponential
5. Suppose the problem changes so that you can move down to the same column or adjacent columns multiple times, but you want to find the minimum falling path sum where you can reuse rows multiple times (i.e., you can revisit rows). Which modification to the bottom-up DP approach correctly handles this variant?
hard
A. Use the original DP but memoize results to avoid recomputation
B. Use the same bottom-up DP but allow cycles by iterating until no dp changes occur
C. Switch to a shortest path algorithm like Bellman-Ford on a graph representing allowed moves
D. Apply greedy approach picking minimum adjacent values repeatedly
Solution
Step 1: Understand the variant with row reuse
Allowing revisiting rows means cycles in the path graph, which breaks the acyclic assumption of DP.
Step 2: Identify suitable algorithm
Model the problem as a graph with edges representing allowed moves and use Bellman-Ford to find shortest paths with possible cycles.