vault backup: 2022-07-20 22:44:44
This commit is contained in:
parent
04d36288ad
commit
4727c3321a
147
OJ notes/pages/Leetcode House-Robber.md
Normal file
147
OJ notes/pages/Leetcode House-Robber.md
Normal file
|
@ -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<int> cache;
|
||||||
|
int robbery(vector<int> &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<int> &nums) {
|
||||||
|
// Version one
|
||||||
|
// Recursion
|
||||||
|
// rob current store: nums[i] + rob(i - 2)
|
||||||
|
// don't rob current home: rob(i - 1)
|
||||||
|
cache = vector<int>(nums.size(), -1);
|
||||||
|
|
||||||
|
return robbery(nums, nums.size() - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Stage 3:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
|
Loading…
Reference in a new issue