Practice
def rob(root):
def dfs(node):
if not node:
return (0, 0) # (not_rob, rob)
left = dfs(node.left)
right = dfs(node.right)
rob_node = node.val + left[1] + right[1] # Bug here
not_rob_node = max(left) + max(right)
return (not_rob_node, rob_node)
return max(dfs(root))Solution
Step 1: Understand rob_node calculation
When robbing current node, children cannot be robbed, so we must add left[0] and right[0] (not_rob values).Step 2: Identify bug
The code incorrectly adds left[1] and right[1] (rob values), causing double counting and invalid solutions.Final Answer:
Option B -> Option BQuick Check:
Correct rob_node uses not_rob children sums [OK]
- Mixing rob and not_rob indices in tuple
Solution
Step 1: Examine sorting order
Sorting by width ascending and height ascending causes envelopes with same width but increasing height to be counted incorrectly in LIS.Step 2: Understand LIS requirement
Heights must be sorted descending for equal widths to avoid counting invalid envelopes.Final Answer:
Option A -> Option AQuick Check:
Sorting order bug leads to wrong LIS and incorrect nesting count [OK]
- Sorting both dimensions ascending instead of height descending
- Misusing bisect functions
- Incorrectly extracting heights
Solution
Step 1: Understand reuse means indices can repeat or be equal
Original DP requires j < i to ensure strictly increasing indices; reuse breaks this.Step 2: Modify DP loops to allow i ≤ j and update counts accordingly
Allowing i ≤ j and updating dp[i][diff] with dp[j][diff] + 1 counts subsequences with repeated elements correctly.Step 3: Reject naive reuse of original DP or combinatorial formulas
Original DP with j < i fails; combinatorial formulas are not straightforward here.Final Answer:
Option C -> Option CQuick Check:
Allowing i ≤ j and updating counts handles reuse correctly [OK]
- Trying to reuse original DP without index relaxation
- Assuming combinatorial formula suffices
- Allowing j = i without updating counts properly
Solution
Step 1: Understand the impact of cycles
Allowing node reuse and cycles means paths can be infinite unless cycles are detected and handled.Step 2: Identify correct approach
DFS with cycle detection and DP with visited states prevents infinite loops and correctly computes max sums on simple paths in graphs.Step 3: Why other options fail
Original DP assumes tree structure; greedy ignores path connectivity; converting graph to tree loses valid paths.Final Answer:
Option C -> Option CQuick Check:
Cycle-aware DFS with DP is necessary for graphs with cycles [OK]
- Ignoring cycles causes infinite loops
- Greedy fails on path connectivity
- Tree DP invalid on graphs
Solution
Step 1: Understand reuse breaks greedy assumptions
Greedy relies on no reuse; allowing reuse requires exploring multiple sequences.Step 2: Use DP with memoization
DP can handle repeated pairs by caching results for each state, ensuring correctness.Step 3: Reject naive greedy and unsorted DP
Greedy fails with reuse; unsorted DP is inefficient and incorrect without sorting.Final Answer:
Option D -> Option DQuick Check:
Memoized DP handles reuse correctly [OK]
- Trying to fix greedy by relaxing conditions
- Ignoring sorting or memoization in DP
- Assuming bottom-up DP without sorting suffices
