Skip to content

Commit 4b80b47

Browse files
rain84yanglbme
andauthored
feat: add solutions to lc problem: No.0198 (doocs#3249)
Co-authored-by: Libin YANG <[email protected]>
1 parent b1c2f99 commit 4b80b47

23 files changed

+631
-76
lines changed

solution/0100-0199/0198.House Robber/README.md

+215-6
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,174 @@ tags:
5555

5656
<!-- solution:start -->
5757

58-
### 方法一:动态规划
58+
### 方法一:记忆化搜索
59+
60+
我们设计一个函数 $\textit{dfs}(i)$,表示从第 $i$ 间房屋开始偷窃能够得到的最高金额。那么答案即为 $\textit{dfs}(0)$。
61+
62+
函数 $\textit{dfs}(i)$ 的执行过程如下:
63+
64+
- 如果 $i \ge \textit{len}(\textit{nums})$,表示所有房屋都被考虑过了,直接返回 $0$;
65+
- 否则,考虑偷窃第 $i$ 间房屋,那么 $\textit{dfs}(i) = \textit{nums}[i] + \textit{dfs}(i+2)$;不偷窃第 $i$ 间房屋,那么 $\textit{dfs}(i) = \textit{dfs}(i+1)$。
66+
- 返回 $\max(\textit{nums}[i] + \textit{dfs}(i+2), \textit{dfs}(i+1))$。
67+
68+
为了避免重复计算,我们使用记忆化搜索的方法,将 $\textit{dfs}(i)$ 的结果保存在一个数组或哈希表中,每次计算前先查询是否已经计算过,如果计算过直接返回结果。
69+
70+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组长度。
71+
72+
<!-- tabs:start -->
73+
74+
#### Python3
75+
76+
```python
77+
class Solution:
78+
def rob(self, nums: List[int]) -> int:
79+
@cache
80+
def dfs(i: int) -> int:
81+
if i >= len(nums):
82+
return 0
83+
return max(nums[i] + dfs(i + 2), dfs(i + 1))
84+
85+
return dfs(0)
86+
```
87+
88+
#### Java
89+
90+
```java
91+
class Solution {
92+
private Integer[] f;
93+
private int[] nums;
94+
95+
public int rob(int[] nums) {
96+
this.nums = nums;
97+
f = new Integer[nums.length];
98+
return dfs(0);
99+
}
100+
101+
private int dfs(int i) {
102+
if (i >= nums.length) {
103+
return 0;
104+
}
105+
if (f[i] == null) {
106+
f[i] = Math.max(nums[i] + dfs(i + 2), dfs(i + 1));
107+
}
108+
return f[i];
109+
}
110+
}
111+
```
112+
113+
#### C++
114+
115+
```cpp
116+
class Solution {
117+
public:
118+
int rob(vector<int>& nums) {
119+
int n = nums.size();
120+
int f[n];
121+
memset(f, -1, sizeof(f));
122+
auto dfs = [&](auto&& dfs, int i) -> int {
123+
if (i >= n) {
124+
return 0;
125+
}
126+
if (f[i] < 0) {
127+
f[i] = max(nums[i] + dfs(dfs, i + 2), dfs(dfs, i + 1));
128+
}
129+
return f[i];
130+
};
131+
return dfs(dfs, 0);
132+
}
133+
};
134+
```
135+
136+
#### Go
137+
138+
```go
139+
func rob(nums []int) int {
140+
n := len(nums)
141+
f := make([]int, n)
142+
for i := range f {
143+
f[i] = -1
144+
}
145+
var dfs func(int) int
146+
dfs = func(i int) int {
147+
if i >= n {
148+
return 0
149+
}
150+
if f[i] < 0 {
151+
f[i] = max(nums[i]+dfs(i+2), dfs(i+1))
152+
}
153+
return f[i]
154+
}
155+
return dfs(0)
156+
}
157+
```
158+
159+
#### TypeScript
160+
161+
```ts
162+
function rob(nums: number[]): number {
163+
const n = nums.length;
164+
const f: number[] = Array(n).fill(-1);
165+
const dfs = (i: number): number => {
166+
if (i >= n) {
167+
return 0;
168+
}
169+
if (f[i] < 0) {
170+
f[i] = Math.max(nums[i] + dfs(i + 2), dfs(i + 1));
171+
}
172+
return f[i];
173+
};
174+
return dfs(0);
175+
}
176+
```
177+
178+
#### Rust
179+
180+
```rust
181+
impl Solution {
182+
pub fn rob(nums: Vec<i32>) -> i32 {
183+
fn dfs(i: usize, nums: &Vec<i32>, f: &mut Vec<i32>) -> i32 {
184+
if i >= nums.len() {
185+
return 0;
186+
}
187+
if f[i] < 0 {
188+
f[i] = (nums[i] + dfs(i + 2, nums, f)).max(dfs(i + 1, nums, f));
189+
}
190+
f[i]
191+
}
192+
193+
let n = nums.len();
194+
let mut f = vec![-1; n];
195+
dfs(0, &nums, &mut f)
196+
}
197+
}
198+
```
199+
200+
#### JavaScript
201+
202+
```js
203+
function rob(nums) {
204+
const n = nums.length;
205+
const f = Array(n).fill(-1);
206+
const dfs = i => {
207+
if (i >= n) {
208+
return 0;
209+
}
210+
if (f[i] < 0) {
211+
f[i] = Math.max(nums[i] + dfs(i + 2), dfs(i + 1));
212+
}
213+
return f[i];
214+
};
215+
return dfs(0);
216+
}
217+
```
218+
219+
<!-- tabs:end -->
220+
221+
<!-- solution:end -->
222+
223+
<!-- solution:start -->
224+
225+
### 方法二:动态规划
59226

60227
我们定义 $f[i]$ 表示前 $i$ 间房屋能偷窃到的最高总金额,初始时 $f[0]=0$, $f[1]=nums[0]$。
61228

@@ -161,12 +328,28 @@ function rob(nums: number[]): number {
161328
```rust
162329
impl Solution {
163330
pub fn rob(nums: Vec<i32>) -> i32 {
164-
let mut f = [0, 0];
165-
for x in nums {
166-
f = [f[0].max(f[1]), f[0] + x];
331+
let n = nums.len();
332+
let mut f = vec![0; n + 1];
333+
f[1] = nums[0];
334+
for i in 2..=n {
335+
f[i] = f[i - 1].max(f[i - 2] + nums[i - 1]);
167336
}
168-
f[0].max(f[1])
337+
f[n]
338+
}
339+
}
340+
```
341+
342+
#### JavaScript
343+
344+
```js
345+
function rob(nums) {
346+
const n = nums.length;
347+
const f = Array(n + 1).fill(0);
348+
f[1] = nums[0];
349+
for (let i = 2; i <= n; ++i) {
350+
f[i] = Math.max(f[i - 1], f[i - 2] + nums[i - 1]);
169351
}
352+
return f[n];
170353
}
171354
```
172355

@@ -176,7 +359,7 @@ impl Solution {
176359

177360
<!-- solution:start -->
178361

179-
### 方法二:动态规划(空间优化)
362+
### 方法三:动态规划(空间优化)
180363

181364
我们注意到,当 $i \gt 2$ 时,$f[i]$ 只和 $f[i-1]$ 与 $f[i-2]$ 有关,因此我们可以使用两个变量代替数组,将空间复杂度降到 $O(1)$。
182365

@@ -250,6 +433,32 @@ function rob(nums: number[]): number {
250433
}
251434
```
252435

436+
#### Rust
437+
438+
```rust
439+
impl Solution {
440+
pub fn rob(nums: Vec<i32>) -> i32 {
441+
let mut f = [0, 0];
442+
for x in nums {
443+
f = [f[0].max(f[1]), f[0] + x];
444+
}
445+
f[0].max(f[1])
446+
}
447+
}
448+
```
449+
450+
#### JavaScript
451+
452+
```js
453+
function rob(nums) {
454+
let [f, g] = [0, 0];
455+
for (const x of nums) {
456+
[f, g] = [Math.max(f, g), f + x];
457+
}
458+
return Math.max(f, g);
459+
}
460+
```
461+
253462
<!-- tabs:end -->
254463

255464
<!-- solution:end -->

0 commit comments

Comments
 (0)