From 2f2093e938d83ae8ae5daf1216a6fdcbdb94ed99 Mon Sep 17 00:00:00 2001 From: Darsh Kantaria <91107260+darshkantaria@users.noreply.github.com> Date: Fri, 10 Oct 2025 09:54:56 +0530 Subject: [PATCH] Added House Robber II (Dynamic Programming, C++) Implemented LeetCode Problem #213 - House Robber II in C++ using DP (Tabulation, O(n), O(1)) --- dynamic_programming/HouseRobberII.cpp | 105 ++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 dynamic_programming/HouseRobberII.cpp diff --git a/dynamic_programming/HouseRobberII.cpp b/dynamic_programming/HouseRobberII.cpp new file mode 100644 index 00000000000..bf43ce3357f --- /dev/null +++ b/dynamic_programming/HouseRobberII.cpp @@ -0,0 +1,105 @@ +/* +========================================================= +🏠 Problem: House Robber II +========================================================= +πŸ”— LeetCode Link: +https://leetcode.com/problems/house-robber-ii/ + +πŸ“˜ Problem Statement: +You are a professional robber planning to rob houses along a street. +Each house has a certain amount of money. All houses are arranged in a circle, +which means the first and last houses are adjacent. +You cannot rob two adjacent houses. + +Return the maximum amount of money you can rob tonight without alerting the police. + +--------------------------------------------------------- +🧠 Approach: Dynamic Programming (Tabulation) +--------------------------------------------------------- +- Because the first and last houses are adjacent, we cannot include both. +- So, we compute two scenarios: + 1️⃣ Rob houses from index [0 ... n-2] (skip last) + 2️⃣ Rob houses from index [1 ... n-1] (skip first) +- Take the maximum of both cases. + +--------------------------------------------------------- +⏱️ Time Complexity: O(n) +πŸ’Ύ Space Complexity: O(1) +--------------------------------------------------------- +πŸ“Œ Points to Remember: +- For circular arrangements, always consider two linear cases. +- DP base cases are mandatory (at least one). +- Transition: dp[i] = max(dp[i-1], dp[i-2] + nums[i]) +--------------------------------------------------------- +*/ + +#include +using namespace std; + +class Solution { +public: + int robLinear(vector& nums, int start, int end){ + int n = end - start + 1; // we don’t always use the full array (so we can't write nums.size()) + + // Edge cases: + if(n == 0) return 0; + if(n == 1) return nums[start]; + + // Initialize the first two states + int prev2 = nums[start]; // dp[i-2] + int prev1 = max(nums[start], nums[start + 1]); // dp[i-1] + + // Iterate over the rest of the houses + for(int i = start + 2; i <= end; i++){ + int curr = max(prev2 + nums[i], prev1); + prev2 = prev1; // move the window forward + prev1 = curr; + } + + return prev1; + } + + int rob(vector& nums){ + int n = nums.size(); + + // Edge cases + if(n == 1) return nums[0]; + if(n == 2) return max(nums[0], nums[1]); + + // Case 1: Rob houses from index 0 to n-2 (exclude last) + int skipLast = robLinear(nums, 0, n - 2); + + // Case 2: Rob houses from index 1 to n-1 (exclude first) + int skipFirst = robLinear(nums, 1, n - 1); + + // Take maximum of both cases + return max(skipLast, skipFirst); + } +}; + + +/* +========================================================= +βœ… Example Test (Uncomment to run locally) +========================================================= +int main() { + Solution sol; + vector nums = {2, 3, 2}; + cout << "Maximum money robbed: " << sol.rob(nums) << endl; + return 0; +} +========================================================= + +Time complexity = O(n) and Space complexity = O(1) using Dynamic Programming (Tabulation approach) + +First & Last houses are adjacent so we can either skip first house or last +Solve for both separately and then return 'maximum' of it + +Thumb rule of DP: + - We always need 'at least one' base case (bcz DP is recurrence based) + - Always >= 1 base cases + +If absolute indices --> i<=end +If relative indices --> i