diff --git a/OJ notes/pages/Leetcode House-Robber.md b/OJ notes/pages/Leetcode House-Robber.md new file mode 100644 index 0000000..cac63e5 --- /dev/null +++ b/OJ notes/pages/Leetcode House-Robber.md @@ -0,0 +1,147 @@ +# Leetcode House-Robber + +#### 2022-07-20 22:21 + +> ##### Algorithms: +> #algorithm #dynamic_programming +> ##### Difficulty: +> #coding_problem #difficulty-medium +> ##### Additional tags: +> #leetcode +> ##### Revisions: +> N/A + +##### Related topics: +```expander +tag:#dynamic_programming +``` + + + +##### Links: +- [Link to problem](https://leetcode.com/problems/house-robber/) +- [Tutorial and explanation on DP](https://leetcode.com/problems/house-robber/discuss/156523/From-good-to-great.-How-to-approach-most-of-DP-problems.) +___ +### Problem + +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**. + +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**_. + +#### Examples + +**Example 1:** + +```markdown +**Input:** nums = [1,2,3,1] +**Output:** 4 +**Explanation:** Rob house 1 (money = 1) and then rob house 3 (money = 3). +Total amount you can rob = 1 + 3 = 4. +``` + +**Example 2:** + +```markdown +**Input:** nums = [2,7,9,3,1] +**Output:** 12 +**Explanation:** Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1). +Total amount you can rob = 2 + 9 + 1 = 12. +``` + +#### Constraints + +- `1 <= nums.length <= 100` +- `0 <= nums[i] <= 400` + +### Thoughts + +> [!summary] +> This is a #dynamic_programming problem. + +According to [This tuturial](https://leetcode.com/problems/house-robber/discuss/156523/From-good-to-great.-How-to-approach-most-of-DP-problems.), the code can be derived from 3 stages: + +#### Stage 1: Find recursive (unoptimized) solution + +The robbing problem can be simplified as follows: + +> Whether to rob or not? +> - if rob, profit = nums[n] + rob(nums, n - 2) +> - else, profit = rob(nums, n - 1) + +The recursive solution can be represented as follows: + +##### Base case: nums.size() = 0 || 1 || 2 + +##### Pseudo code: + +- check for base case +- return max(robbery(nums, n - 1), robbery(nums, n - 2) + nums[n]) + +#### Stage 2: Find recursive solution with cache + +Since the core of DP as about re-using answers from before, we can cache the answers to make the code faster. + +##### Pseudo code: + +- Check for base case +- if cache found, return +- assign the computed value to cache +- return the cached value + +#### Stage 3: Find iterative solution with caching + +By using iterative, we can use less memory than recursion (return stack). + +We start from bottom to top, rather than from top to down, and use the cached answer to proceed to the final answer + +#### Stage 4: Optimize it by using variables rather than hash table based caching + +This can be different from problem to problem, but for this case, +we achieve constant space complexity using variables. + +### Solution + +#### Stage 1: + +TLE, I didn't save this one + +#### Stage 2: + +```cpp +class Solution { + vector cache; + int robbery(vector &nums, int nextLoc) { + // base cases: + // nextLoc == 0, return nums[1] + // nextLoc == 1, return nums[2] + if (nextLoc < 0) { + return 0; + } + + if (cache[nextLoc] != -1) { + return cache[nextLoc]; + } + + cache[nextLoc] = max(robbery(nums, nextLoc - 1), + robbery(nums, nextLoc - 2) + nums[nextLoc]); + + return cache[nextLoc]; + } + +public: + int rob(vector &nums) { + // Version one + // Recursion + // rob current store: nums[i] + rob(i - 2) + // don't rob current home: rob(i - 1) + cache = vector(nums.size(), -1); + + return robbery(nums, nums.size() - 1); + } +}; +``` + +#### Stage 3: + +```cpp +