Initialize profit array with zeros and maxDiff array with -prices[0] for all transaction counts (0 to 2). This sets the base state before processing days.
💡 Starting with zero profit and maxDiff as negative first price models the initial buying cost for each transaction count.
Line:profit = [0] * 3
maxDiff = [-prices[0]] * 3
💡 Initial arrays represent no profit and the cost of buying on day 0 for each transaction count.
fill_cells
Start day 1 iteration (price=3), update for k=2
For day 1 (price=3), update profit[2] by comparing current profit[2] and price + maxDiff[2]. Then update maxDiff[2] using profit[1] - price.
💡 Updating profit and maxDiff for highest transaction count first ensures dependencies on lower counts are preserved.
💡 Profit for 1 transaction improves to 4 by selling at price 4.
reconstruct
Return final profit for 2 transactions
After processing all days, return profit[2] which holds the maximum profit achievable with up to 2 transactions.
💡 The final profit value is the answer to the problem.
Line:return profit[2]
💡 The algorithm successfully computed the maximum profit of 6 for two transactions.
def maxProfit(prices):
n = len(prices)
if n == 0:
return 0
profit = [0] * 3 # STEP 1
maxDiff = [-prices[0]] * 3 # STEP 1
for i in range(1, n): # STEP 2-15
for k in range(2, 0, -1):
profit[k] = max(profit[k], prices[i] + maxDiff[k]) # STEP update profit
maxDiff[k] = max(maxDiff[k], profit[k-1] - prices[i]) # STEP update maxDiff
return profit[2] # STEP 16
if __name__ == '__main__':
prices = [3,3,5,0,0,3,1,4]
print(maxProfit(prices)) # Expected output: 6
📊
Best Time - 2 Transactions - Watch the Algorithm Execute, Step by Step
Watching each update to profit and maxDiff arrays reveals how the algorithm balances buying and selling decisions over time to maximize total profit.
Step 1/16
·Active fill★Answer cell
Item 0 - wt:3 val:0
i\w
0
1
2
i=0
0
0
0
i=1
-3
-3
-3
profit[0] = 0
Item 1 - wt:3 val:0
i\w
0
1
2
i=0
0
0
0
i=1
-3
-3
-3
profit[2] updated
Item 1 - wt:3 val:0
i\w
0
1
2
i=0
0
0
0
i=1
-3
-3
-3
profit[1] updated
Item 2 - wt:5 val:2
i\w
0
1
2
i=0
0
0
2
i=1
-3
-3
-3
profit[2] updated to 2
Item 2 - wt:5 val:2
i\w
0
1
2
i=0
0
2
2
i=1
-3
-3
-3
profit[1] updated to 2
Item 3 - wt:0 val:2
i\w
0
1
2
i=0
0
2
2
i=1
-3
-3
2
maxDiff[2] updated to 2
Item 3 - wt:0 val:2
i\w
0
1
2
i=0
0
2
2
i=1
0
-3
2
maxDiff[1] updated to 0
Item 4 - wt:0 val:2
i\w
0
1
2
i=0
0
2
2
i=1
0
-3
2
profit[2] unchanged
Item 4 - wt:0 val:2
i\w
0
1
2
i=0
0
2
2
i=1
0
-3
2
profit[1] unchanged
Item 5 - wt:3 val:5
i\w
0
1
2
i=0
0
2
5
i=1
0
-3
2
profit[2] updated to 5
Item 5 - wt:3 val:5
i\w
0
1
2
i=0
0
3
5
i=1
0
-3
2
profit[1] updated to 3
Item 6 - wt:1 val:5
i\w
0
1
2
i=0
0
3
5
i=1
0
-3
2
maxDiff[2] unchanged
Item 6 - wt:1 val:5
i\w
0
1
2
i=0
0
3
5
i=1
0
-3
2
profit[1] unchanged
Item 7 - wt:4 val:6
i\w
0
1
2
i=0
0
3
6
i=1
0
-3
2
profit[2] updated to 6
Item 7 - wt:4 val:6
i\w
0
1
2
i=0
0
4
6
i=1
0
-3
2
profit[1] updated to 4
Item 7 - wt:4 val:6
i\w
0
1
2
i=0
0
4
6
i=1
0
-3
2
final profit[2] = 6
Key Takeaways
✓ The algorithm maintains two arrays, profit and maxDiff, to track the best profits and buying opportunities for each transaction count.
This separation clarifies how buying and selling decisions are optimized independently but combined to maximize profit.
✓ Updating transaction counts in reverse order (from 2 down to 1) preserves dependencies on previous transaction profits.
This order ensures that maxDiff uses the correct profit values from the previous transaction count.
✓ maxDiff array captures the best net cost of buying considering profits from previous transactions, enabling efficient profit updates.
This insight is hard to see from code alone but becomes clear when watching maxDiff values update step-by-step.
Practice
(1/5)
1. You are given a string of digits representing an encoded message where 'A' = 1, 'B' = 2, ..., 'Z' = 26. You need to find the total number of ways to decode the message. Which algorithmic approach guarantees an efficient and correct solution for this problem?
easy
A. Dynamic programming that builds the count of decodings using previous results
B. Sorting the digits and counting unique permutations
C. Depth-first search without memoization exploring all decoding paths
D. Greedy algorithm that picks the largest valid two-digit number at each step
Solution
Step 1: Understand problem constraints
The problem requires counting all valid decodings, which can overlap and depend on previous computations.
Step 2: Identify suitable algorithm
Dynamic programming efficiently counts ways by reusing previous results, avoiding exponential recomputation unlike naive DFS, and greedy or sorting approaches do not guarantee correctness.
Final Answer:
Option A -> Option A
Quick Check:
DP handles overlapping subproblems and optimal substructure [OK]
Hint: Count ways using previous results, not greedy or brute force [OK]
Common Mistakes:
Thinking greedy or sorting solves decoding count correctly
2. You are given a list of non-negative integers representing the amount of money in each house along a street. You want to maximize the total amount you can rob tonight without robbing two adjacent houses. Which algorithmic approach guarantees finding the optimal solution efficiently?
easy
A. Dynamic programming that considers robbing or skipping each house to maximize total
B. A greedy algorithm that always picks the house with the maximum amount next
C. Sorting the houses by amount and picking the top half
D. Depth-first search exploring all subsets of houses
Solution
Step 1: Understand problem constraints
The problem requires maximizing sum without robbing adjacent houses, which is a classic overlapping subproblems scenario.
Step 2: Identify suitable algorithm
Dynamic programming fits because it explores choices at each house (rob or skip) and uses previous results to build optimal solution.
Final Answer:
Option A -> Option A
Quick Check:
Greedy fails on cases like [2,7,9,3,1], DP finds max 12 [OK]
Hint: DP handles overlapping subproblems and optimal substructure [OK]
Common Mistakes:
Greedy approach fails on non-adjacent constraints
3. Given the following code for the Jump Game II problem, what is the value of the variable jumps returned when the input is [2,1,1]?
easy
A. 3
B. 2
C. 1
D. 0
Solution
Step 1: Trace variables for input [2,1,1]
n=3, loop i in [0,1].
- i=0: furthest = max(0, 0+2) = 2; i == current_end (0), so jumps = 1, current_end = 2
- i=1: furthest = max(2, 1+1) = 2; i != current_end (2), no jump increment
Loop ends.
Step 2: Return jumps
jumps = 1 is returned, meaning minimum 1 jump to reach the end.
Final Answer:
Option C -> Option C
Quick Check:
One jump from index 0 to last index covers entire array [OK]
Hint: Increment jumps only when i reaches current_end [OK]
Common Mistakes:
Incrementing jumps too early or too late
Off-by-one errors in loop range
Misunderstanding when to update current_end
4. What is the time complexity of the optimal space-optimized bottom-up dynamic programming solution for the decoding ways problem, and why?
medium
A. O(n) but with O(n) auxiliary space for dp array
B. O(n^2) because each position checks all previous positions
C. O(2^n) due to recursive branching without memoization
D. O(n) because each character is processed once with constant checks
Solution
Step 1: Analyze loop iterations
The code iterates through the string once, processing each character exactly once.
Step 2: Check operations per iteration
Each iteration performs constant time checks for single and two-digit validity, no nested loops.
Final Answer:
Option D -> Option D
Quick Check:
Linear scan with constant work per step -> O(n) time [OK]
Hint: One pass with constant work per character -> O(n) time [OK]
Common Mistakes:
Assuming nested loops cause O(n^2)
Confusing recursion without memoization complexity
5. The following code attempts to solve the Word Break problem. Identify the line that contains a subtle bug that can cause incorrect results or inefficiency.
medium
A. Line 5: Incorrect base case initialization
B. Line 1: Using list instead of set for word lookup
C. Line 8: Incorrect substring indices
D. Line 9: Setting dp[i] to True without checking all lengths
Solution
Step 1: Analyze data structure for word lookup
Using a list for word_set causes substring membership checks to be O(n) instead of O(1), leading to inefficiency and possible timeouts.
Step 2: Verify other lines
Base case dp[0] = True is correct; substring indices are correct; missing break after dp[i] = True causes inefficiency but not incorrectness.
Final Answer:
Option B -> Option B
Quick Check:
List lookup is linear, set lookup is constant time [OK]
Hint: Use set for O(1) membership, not list [OK]
Common Mistakes:
Forgetting to break inner loop
Misindexing substring
Incorrect base case initialization
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.