Skip to content

Commit 2f2093e

Browse files
Added House Robber II (Dynamic Programming, C++)
Implemented LeetCode Problem #213 - House Robber II in C++ using DP (Tabulation, O(n), O(1))
1 parent ba0d3ff commit 2f2093e

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
=========================================================
3+
🏠 Problem: House Robber II
4+
=========================================================
5+
🔗 LeetCode Link:
6+
https://leetcode.com/problems/house-robber-ii/
7+
8+
📘 Problem Statement:
9+
You are a professional robber planning to rob houses along a street.
10+
Each house has a certain amount of money. All houses are arranged in a circle,
11+
which means the first and last houses are adjacent.
12+
You cannot rob two adjacent houses.
13+
14+
Return the maximum amount of money you can rob tonight without alerting the police.
15+
16+
---------------------------------------------------------
17+
🧠 Approach: Dynamic Programming (Tabulation)
18+
---------------------------------------------------------
19+
- Because the first and last houses are adjacent, we cannot include both.
20+
- So, we compute two scenarios:
21+
1️⃣ Rob houses from index [0 ... n-2] (skip last)
22+
2️⃣ Rob houses from index [1 ... n-1] (skip first)
23+
- Take the maximum of both cases.
24+
25+
---------------------------------------------------------
26+
⏱️ Time Complexity: O(n)
27+
💾 Space Complexity: O(1)
28+
---------------------------------------------------------
29+
📌 Points to Remember:
30+
- For circular arrangements, always consider two linear cases.
31+
- DP base cases are mandatory (at least one).
32+
- Transition: dp[i] = max(dp[i-1], dp[i-2] + nums[i])
33+
---------------------------------------------------------
34+
*/
35+
36+
#include <bits/stdc++.h>
37+
using namespace std;
38+
39+
class Solution {
40+
public:
41+
int robLinear(vector<int>& nums, int start, int end){
42+
int n = end - start + 1; // we don’t always use the full array (so we can't write nums.size())
43+
44+
// Edge cases:
45+
if(n == 0) return 0;
46+
if(n == 1) return nums[start];
47+
48+
// Initialize the first two states
49+
int prev2 = nums[start]; // dp[i-2]
50+
int prev1 = max(nums[start], nums[start + 1]); // dp[i-1]
51+
52+
// Iterate over the rest of the houses
53+
for(int i = start + 2; i <= end; i++){
54+
int curr = max(prev2 + nums[i], prev1);
55+
prev2 = prev1; // move the window forward
56+
prev1 = curr;
57+
}
58+
59+
return prev1;
60+
}
61+
62+
int rob(vector<int>& nums){
63+
int n = nums.size();
64+
65+
// Edge cases
66+
if(n == 1) return nums[0];
67+
if(n == 2) return max(nums[0], nums[1]);
68+
69+
// Case 1: Rob houses from index 0 to n-2 (exclude last)
70+
int skipLast = robLinear(nums, 0, n - 2);
71+
72+
// Case 2: Rob houses from index 1 to n-1 (exclude first)
73+
int skipFirst = robLinear(nums, 1, n - 1);
74+
75+
// Take maximum of both cases
76+
return max(skipLast, skipFirst);
77+
}
78+
};
79+
80+
81+
/*
82+
=========================================================
83+
✅ Example Test (Uncomment to run locally)
84+
=========================================================
85+
int main() {
86+
Solution sol;
87+
vector<int> nums = {2, 3, 2};
88+
cout << "Maximum money robbed: " << sol.rob(nums) << endl;
89+
return 0;
90+
}
91+
=========================================================
92+
93+
Time complexity = O(n) and Space complexity = O(1) using Dynamic Programming (Tabulation approach)
94+
95+
First & Last houses are adjacent so we can either skip first house or last
96+
Solve for both separately and then return 'maximum' of it
97+
98+
Thumb rule of DP:
99+
- We always need 'at least one' base case (bcz DP is recurrence based)
100+
- Always >= 1 base cases
101+
102+
If absolute indices --> i<=end
103+
If relative indices --> i<n (i = 2 ... n-1)
104+
=========================================================
105+
*/

0 commit comments

Comments
 (0)