|
| 1 | +# https://leetcode.com/problems/house-robber-ii/ |
| 2 | + |
| 3 | +from typing import List |
| 4 | + |
| 5 | +class Solution: |
| 6 | + def rob_on(self, nums: List[int]) -> int: |
| 7 | + """ |
| 8 | + [Complexity] |
| 9 | + - TC: O(n) |
| 10 | + - SC: O(n) |
| 11 | +
|
| 12 | + [Approach] |
| 13 | + 집들이 원을 이루고 있고 인접한 두 집을 모두 방문하면 안 되기 때문에, 다음과 같이 두 가지 상황으로 max money를 구한다. |
| 14 | + (원형이라는 점을 고려하지 않으면 첫 번째 집과 마지막 집을 모두 방문하게 될 수도 있기 때문) |
| 15 | + (1) 첫 번째 집을 제외 |
| 16 | + (2) 마지막 집을 제외 |
| 17 | + 그리고 두 값 중 큰 값을 반환한다. |
| 18 | +
|
| 19 | + dp[i] = nums[i]까지 확인했을 때의 max money |
| 20 | + dp[i] = max(dp[i - 1], dp[i - 2] + num) |
| 21 | + """ |
| 22 | + n = len(nums) |
| 23 | + |
| 24 | + # early stop |
| 25 | + if n <= 3: |
| 26 | + return max(nums) |
| 27 | + |
| 28 | + dp1 = [0] * (n - 1) # 마지막 집 제외: nums[0] ~ nums[n - 2] |
| 29 | + dp2 = [0] * (n - 1) # 첫 번째 집 제외: nums[1] ~ nums[n - 1] |
| 30 | + |
| 31 | + # initialize |
| 32 | + dp1[0], dp2[0] = nums[0], nums[1] |
| 33 | + dp1[1], dp2[1] = max(dp1[0], nums[1]), max(dp2[0], nums[2]) |
| 34 | + |
| 35 | + for i in range(2, n - 1): |
| 36 | + dp1[i] = max(dp1[i - 1], dp1[i - 2] + nums[i]) |
| 37 | + dp2[i] = max(dp2[i - 1], dp2[i - 2] + nums[i + 1]) |
| 38 | + |
| 39 | + return max(dp1[-1], dp2[-1]) |
| 40 | + |
| 41 | + def rob(self, nums: List[int]) -> int: |
| 42 | + """ |
| 43 | + [Complexity] |
| 44 | + - TC: O(n) |
| 45 | + - SC: O(1) |
| 46 | +
|
| 47 | + [Approach] |
| 48 | + 이전 O(n) space DP 풀이에서 dp[i] 값을 구하기 위해 dp[i - 1] & dp[i - 2] 값만 참고하므로, |
| 49 | + O(1) space로 optimize 할 수 있다. |
| 50 | + """ |
| 51 | + n = len(nums) |
| 52 | + |
| 53 | + # early stop |
| 54 | + if n <= 3: |
| 55 | + return max(nums) |
| 56 | + |
| 57 | + # p2 = dp[i - 2], p1 = dp[i - 1] |
| 58 | + f_p2 = f_p1 = 0 # 마지막 집 제외: nums[0] ~ nums[n - 2] |
| 59 | + l_p2 = l_p1 = 0 # 첫 번째 집 제외: nums[1] ~ nums[n - 1] |
| 60 | + |
| 61 | + for i in range(n - 1): |
| 62 | + f_p2, f_p1 = f_p1, max(f_p1, f_p2 + nums[i]) |
| 63 | + l_p2, l_p1 = l_p1, max(l_p1, l_p2 + nums[i + 1]) |
| 64 | + |
| 65 | + return max(f_p1, l_p1) |
0 commit comments