Skip to content

Commit b11d667

Browse files
committed
House Robber
1 parent 6f514c5 commit b11d667

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

198.house_robber/robber.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# 198. House Robber
2+
# Topics: 'Array', 'Dynamic Programming'
3+
# Level: 'Medium'
4+
5+
# 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.
6+
7+
# 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.
8+
9+
10+
11+
# Example 1:
12+
13+
# Input: nums = [1,2,3,1]
14+
# Output: 4
15+
# Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
16+
# Total amount you can rob = 1 + 3 = 4.
17+
18+
# Example 2:
19+
20+
# Input: nums = [2,7,9,3,1]
21+
# Output: 12
22+
# Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
23+
# Total amount you can rob = 2 + 9 + 1 = 12.
24+
25+
26+
27+
# Constraints:
28+
29+
# 1 <= nums.length <= 100
30+
# 0 <= nums[i] <= 400
31+
32+
from typing import List
33+
34+
class Solution:
35+
def rob(self, nums: List[int]) -> int:
36+
rob1, rob2 = 0, 0
37+
for num in nums:
38+
rob1, rob2 = rob2, max(num + rob1, rob2)
39+
return rob2
40+
41+
# def rob(self, nums: List[int]) -> int:
42+
# if len(nums) == 1:
43+
# return nums[0]
44+
# memo = [-1]*(len(nums)+1)
45+
# return self.dfs(0, nums, memo)
46+
47+
# def dfs(self, i: int, nums: List[int], memo: List[int]) -> int:
48+
# if i > len(nums)-1:
49+
# return 0
50+
# if memo[i] != -1:
51+
# return memo[i]
52+
# memo[i] = max(nums[i] + self.dfs(i+2, nums, memo), self.dfs(i+1, nums, memo))
53+
# return memo[i]

198.house_robber/test_robber.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import unittest
2+
from typing import List
3+
from robber import Solution
4+
5+
class TestHouseRobber(unittest.TestCase):
6+
7+
def test_example1(self):
8+
self.assertEqual(Solution().rob([1,2,3,1]), 4)
9+
10+
def test_example2(self):
11+
self.assertEqual(Solution().rob([2,7,9,3,1]), 12)
12+
13+
def test_single_element(self):
14+
self.assertEqual(Solution().rob([5]), 5)
15+
16+
def test_two_elements(self):
17+
self.assertEqual(Solution().rob([2,1]), 2)
18+
self.assertEqual(Solution().rob([1,2]), 2)
19+
20+
def test_all_zeroes(self):
21+
self.assertEqual(Solution().rob([0,0,0,0]), 0)
22+
23+
def test_strictly_increasing(self):
24+
# [1,2,3,4,5] → choose 1 + 3 + 5 = 9
25+
self.assertEqual(Solution().rob([1,2,3,4,5]), 9)
26+
27+
def test_uniform_values(self):
28+
# [5,5,5,5,5] → 5+5+5 = 15
29+
self.assertEqual(Solution().rob([5,5,5,5,5]), 15)
30+
31+
def test_large_input(self):
32+
arr = [400]*100
33+
# best = sum of every second: 50 * 400 = 20000
34+
self.assertEqual(Solution().rob(arr), 20000)
35+
36+
# A brute-force solver for validation
37+
def brute(self, nums):
38+
from functools import lru_cache
39+
@lru_cache(None)
40+
def dfs(i):
41+
if i >= len(nums):
42+
return 0
43+
return max(nums[i] + dfs(i+2), dfs(i+1))
44+
return dfs(0)
45+
46+
def test_random_small(self):
47+
import random
48+
for _ in range(30):
49+
n = random.randint(1, 8)
50+
arr = [random.randint(0, 20) for _ in range(n)]
51+
self.assertEqual(Solution().rob(arr), self.brute(tuple(arr)))
52+
53+
54+
if __name__ == "__main__":
55+
unittest.main()

0 commit comments

Comments
 (0)