diff --git a/dynamic_programming/house_robber.py b/dynamic_programming/house_robber.py new file mode 100644 index 000000000000..242ed93327fb --- /dev/null +++ b/dynamic_programming/house_robber.py @@ -0,0 +1,48 @@ +def house_robber(houses: list[int]) -> int: + """ + Solves the House Robber problem using memoization (caching). + Returns the maximum amount of money that can be robbed without triggering alarms. + Problem URL: https://leetcode.com/problems/house-robber/ + + Args: + houses: A list of integers representing the amount of money in each house. + Returns: + int: The maximum amount of money that can be robbed without triggering alarms. + Raises: + ValueError: If there are no houses in the input list. + + Examples: + >>> house_robber([2, 3, 2]) + 4 + >>> house_robber([1, 2, 3, 1]) + 4 + >>> house_robber([0, 0, 0, 0]) + 0 + >>> house_robber([10, 15, 20, 25]) + 40 + >>> house_robber([50]) + 50 + >>> house_robber([5, 15, 5, 15, 5]) + 30 + """ + number_of_houses = len(houses) + if number_of_houses == 0: + raise ValueError("There must be at least one house") + + memo = [-1 for _ in range(number_of_houses)] + + def dp(n: int) -> int: + if n >= number_of_houses: + return 0 + # If the house has been visited before, avoid revisiting (Memoization) + if memo[n] != -1: + return memo[n] + + # Decide to rob this house and skip the next, or skip this one + rob = houses[n] + dp(n + 2) + dont_rob = dp(n + 1) + + memo[n] = max(rob, dont_rob) + return memo[n] + + return dp(0)