You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed and is protected by a security system with a color code.
You are given two integer arrays nums and colors, both of length n, where nums[i] is the amount of money in the ith house and colors[i] is the color code of that house.
You cannot rob two adjacent houses if they share the same color code.
Return the maximum amount of money you can rob.
Example 1:
Input: nums = [1,4,3,5], colors = [1,1,2,2]
Output: 9
Explanation:
i = 1 with nums[1] = 4 and i = 3 with nums[3] = 5 because they are non-adjacent.4 + 5 = 9.Example 2:
Input: nums = [3,1,2,4], colors = [2,3,2,2]
Output: 8
Explanation:
i = 0 with nums[0] = 3, i = 1 with nums[1] = 1, and i = 3 with nums[3] = 4.i = 0 and i = 1 have different colors, and house i = 3 is non-adjacent to i = 1.3 + 1 + 4 = 8.Example 3:
Input: nums = [10,1,3,9], colors = [1,1,1,2]
Output: 22
Explanation:
i = 0 with nums[0] = 10, i = 2 with nums[2] = 3, and i = 3 with nums[3] = 9.i = 0 and i = 2 are non-adjacent, and houses i = 2 and i = 3 have different colors.10 + 3 + 9 = 22.
Constraints:
1 <= n == nums.length == colors.length <= 1051 <= nums[i], colors[i] <= 105Problem Overview: You are given an array where each element represents money in a house. Robbing two adjacent houses triggers the alarm, so you must choose houses such that no two selected indices are neighbors while maximizing the total amount stolen.
Approach 1: Brute Force Recursion (O(2^n) time, O(n) space)
Start from the first house and recursively decide whether to rob it or skip it. If you rob house i, the next valid choice is i + 2; if you skip it, move to i + 1. The recursion explores every valid subset of houses and returns the maximum sum. This approach clearly models the decision process but recomputes the same subproblems many times, causing exponential time complexity. The recursion stack requires O(n) space in the worst case.
Approach 2: Top-Down Dynamic Programming (Memoization) (O(n) time, O(n) space)
Use memoization to cache results for each index. Define dp[i] as the maximum amount you can steal starting from house i. During recursion, check if the value is already computed; if so, reuse it instead of recalculating. Each index is evaluated once, turning the exponential recursion into a linear-time solution. This pattern is a classic example of dynamic programming where overlapping subproblems are stored and reused.
Approach 3: Bottom-Up Dynamic Programming (O(n) time, O(n) space)
Instead of recursion, build the solution iteratively. Let dp[i] represent the maximum amount that can be robbed considering houses up to index i. For each house, choose between skipping it (dp[i-1]) or robbing it (nums[i] + dp[i-2]). The transition becomes dp[i] = max(dp[i-1], nums[i] + dp[i-2]). This approach avoids recursion overhead and makes the state transition explicit. It works naturally with the linear structure of the array.
Approach 4: Space-Optimized Dynamic Programming (O(n) time, O(1) space)
The DP state only depends on the previous two values, so storing the entire array is unnecessary. Track two variables: prev1 for the best result up to the previous house and prev2 for the result two houses back. For each value, compute the new maximum using max(prev1, prev2 + value), then shift the variables forward. This reduces memory usage to constant space while preserving linear time. It is the most common implementation for interview solutions involving dynamic programming transitions on sequential data.
Recommended for interviews: The space‑optimized dynamic programming solution is typically expected. Interviewers want to see that you first recognize the overlapping subproblem structure, derive the recurrence max(skip, rob), and then reduce the state to constant space. Discussing the brute force recursion briefly shows you understand the decision tree, but implementing the optimized DP demonstrates strong problem‑solving and optimization skills.
We define two variables f and g, where f represents the maximum amount when the current house is not robbed, and g represents the maximum amount when the current house is robbed. Initially, f = 0 and g = nums[0]. The answer is max(f, g).
Next, we traverse starting from the second house:
f is updated to max(f, g), and g is updated to f + nums[i].f is updated to max(f, g), and g is updated to max(f, g) + nums[i].Finally, return max(f, g).
The time complexity is O(n), where n is the number of houses. The space complexity is O(1).
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Brute Force Recursion | O(2^n) | O(n) | Understanding the decision tree or explaining the base problem before optimization |
| Top-Down DP (Memoization) | O(n) | O(n) | When recursion is easier to reason about and subproblems naturally map to indices |
| Bottom-Up DP | O(n) | O(n) | Iterative implementations where explicit DP arrays improve clarity |
| Space-Optimized DP | O(n) | O(1) | Preferred production and interview solution when memory can be reduced |
LeetCode 3840: House Robber V Solution | Biweekly 176 • CodingHelp • 243 views views
Watch 6 more video solutions →Practice House Robber V with our built-in code editor and test cases.
Practice on FleetCodePractice this problem
Open in Editor