198. House Robber

198. House Robber

Using Python and Go

ยท

4 min read

Problem Statement

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight**without alerting the police.

Examples

Example 1:

Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.

Example 2:

Input: nums = [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.

Constraints

  • 1 <= nums.length <= 100

  • 0 <= nums[i] <= 400

Intuition

This problem is a great fit for solving with recursion. Let's try to tackle it using the recursive framework we explored in The Recursive Journey blog:

  • Identify actual problem: The actual problem here is to find the maximum loot that we can acquire by robbing houses.

$$max(rob(nums))$$

  • Identify sub-problem: If we can rob nth house then we can rob (n-2)th house similarly (i-2th) house.

  • Trust that the base function works: We have confidence in the function that computes the loot. It is designed to work effectively for all sub-problems and deliver the accurate solution.

  • Link actual and sub-problem: Since we have found robHouse(n-2) and robHouse(n-1) we can just do:

robHouse(n) = max(robHouse(n-2),robHouse(n-1))

  • Identify base case: Since we're moving from the nth index of the nums array to the 0th index, we cannot exceed the 0th index. Therefore:

        if house<0:
            return 0
    

    This will make sure recursive function does not go beyond the bounds of nums array.

If you observe, we can solve this issue by moving through the cost array in two directions:

  • from the0th to the nth index

  • from thenth to the 0th index.

The explanation above covers moving through the cost array from the nth index to the 0th index.

The concept for moving through the cost array from the0th index to the nth index remains the same. Only the code we write and the base condition change slightly. Below, we will see code solutions for both approaches.

Code Solution

Going from 0 to n

Python Code:

# TC: O(2^n)
# SC: O(n)
class Solution:
    def rob(self, nums: List[int]) -> int:
        # call recursive function to calculate maximum loot
        # return the maximum loot
        return self.robHouse(0,len(nums),nums)
    def robHouse(self,house,n:int,nums:List[int]):
        # base case
        # since can't rob a house that's not there in the array
        # we return 0
        if house>=n:
            return 0
        # recursive case of robbing the current house
        rob= nums[house]+self.robHouse(house+2,n,nums)
        # recursive ase of not robbing the current house
        dont_rob=self.robHouse(house+1,n,nums)
        # return maximum of rob and dont_rob
        return max(rob,dont_rob)

Going from n to 0

Go Code:

// TC: O(2^n)
// SC: O(n)
func rob(nums []int) int {
    // call the recursive function to calculate loot
    // and return maximum loot
    return robHouse(len(nums)-1,nums)
}
func robHouse(house int, nums []int) int{
    // base case
    // we return 0 if house is less than 0
    // as array can't have -ve size
    if house<0{
        return 0
    }
    // recursive of ronning the current house
    rob:=nums[house]+robHouse(house-2,nums)
    // recursive case of not robbing the current house
    dontRob:=robHouse(house-1,nums)
    // return the maximum of rob and dontRob
    return max(rob,dontRob)
}

func max(a,b int) int{
    if a>b{
        return a
    }
    return b
}
๐Ÿ’ก
Note: The above solutions are absolutely correct, but are not optimized for time complexity. Hence these solutions will give Time Limit Exceeded error when submitted on LeetCode. We will optimize these solutions in the Dynamic Programming Series.

Time and Space complexity

Time Complexity:

$$O(2^n)$$

As for each recursive call we will make two more recursive calls.

Space Complexity:

$$O(n)$$

This is the space allocated for recursive call stack.

Conclusion

As you can see 198. House Robber can be solved using recursion. There are two ways to solve this problem using recursion:

  • from the 0th to the nth index

  • from the nth to the 0th index

Although these are decent solutions, they're just basic recursion without any fancy optimizations. But hey, no worries, we'll dive into those optimizations in the Dynamic Programming series.

I hope you got something useful from this blog post. If you've made it this far, please give it a like and drop your thoughts in the comments. Feel free to share any ideas for making future blog posts better.

ย