Skip to main content

House Robber V - Solution & Explanation

MediumArrayDynamic Programming10 min read
Practice this problem

Problem Statement

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:

  • Choose houses i = 1 with nums[1] = 4 and i = 3 with nums[3] = 5 because they are non-adjacent.
  • Thus, the total amount robbed is 4 + 5 = 9.

Example 2:

Input: nums = [3,1,2,4], colors = [2,3,2,2]

Output: 8

Explanation:

  • Choose houses i = 0 with nums[0] = 3, i = 1 with nums[1] = 1, and i = 3 with nums[3] = 4.
  • This selection is valid because houses i = 0 and i = 1 have different colors, and house i = 3 is non-adjacent to i = 1.
  • Thus, the total amount robbed is 3 + 1 + 4 = 8.

Example 3:

Input: nums = [10,1,3,9], colors = [1,1,1,2]

Output: 22

Explanation:

  • Choose houses i = 0 with nums[0] = 10, i = 2 with nums[2] = 3, and i = 3 with nums[3] = 9.
  • This selection is valid because houses i = 0 and i = 2 are non-adjacent, and houses i = 2 and i = 3 have different colors.
  • Thus, the total amount robbed is 10 + 3 + 9 = 22.

 

Constraints:

  • 1 <= n == nums.length == colors.length <= 105
  • 1 <= nums[i], colors[i] <= 105

Approach Overview

Problem 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.

Solution

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:

  • If the current house has the same color as the previous house, then f is updated to max(f, g), and g is updated to f + nums[i].
  • If the current house has a different color from the previous house, then 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).

Code

Python

Java

C++

Go

TypeScript

Rust

Try this approach in the editor →

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Brute Force RecursionO(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 DPO(n)O(n)Iterative implementations where explicit DP arrays improve clarity
Space-Optimized DPO(n)O(1)Preferred production and interview solution when memory can be reduced

Video Solution

3840. House Robber V (Leetcode Medium) • Programming Live with Larry • 170 views views

Watch 4 more video solutions →

Frequently Asked Questions

Is House Robber V easy or hard?
House Robber V is generally considered a medium-level dynamic programming problem. The main challenge is recognizing the recurrence relation and optimizing space from an O(n) DP array to O(1) variables.
House Robber V Python/Java solution
Most implementations follow the same DP recurrence: max(skip_current, rob_current). The code iterates through the array while updating two variables that track the best previous states. This approach works consistently across Python, Java, C++, Go, TypeScript, and Rust.
How to solve House Robber V in O(n)?
Iterate through the array while maintaining two variables: the maximum money up to the previous house and the maximum up to two houses back. For each value, choose between skipping the house or robbing it and adding its value to the two-back state. This single pass produces the optimal result in linear time.
What is the best approach for House Robber V?
The most efficient approach uses dynamic programming with constant space. Track two running values representing the best result up to the previous house and the house before that. For each house, compute max(previous_best, two_back + current_value). This solves the problem in O(n) time and O(1) space.
Is House Robber V asked at Google/Amazon/Meta?
House Robber style problems are common interview questions at companies like Amazon, Google, and Meta because they test dynamic programming fundamentals. Variants appear frequently in technical interviews to evaluate recurrence design and space optimization.
What data structure is used in House Robber V?
The problem primarily uses arrays combined with dynamic programming states. The DP state can be stored in a separate array or compressed into two variables for constant space optimization.
What is the time complexity of House Robber V?
The optimal dynamic programming solution runs in O(n) time because each house is processed once. The brute force recursive approach takes O(2^n) time due to exploring all combinations, while memoization or bottom-up DP reduces it to linear complexity.

Ready to solve this problem?

Practice House Robber V with our built-in code editor and test cases.

Practice on FleetCode