Skip to content

Commit f39078c

Browse files
authored
Update README.md
1 parent 5570976 commit f39078c

File tree

1 file changed

+198
-81
lines changed
  • solution/0100-0199/0198.House Robber

1 file changed

+198
-81
lines changed

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

Lines changed: 198 additions & 81 deletions
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

@@ -156,6 +323,22 @@ function rob(nums: number[]): number {
156323
}
157324
```
158325

326+
#### Rust
327+
328+
```rust
329+
impl Solution {
330+
pub fn rob(nums: Vec<i32>) -> i32 {
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]);
336+
}
337+
f[n]
338+
}
339+
}
340+
```
341+
159342
#### JavaScript
160343

161344
```js
@@ -170,27 +353,13 @@ function rob(nums) {
170353
}
171354
```
172355

173-
#### Rust
174-
175-
```rust
176-
impl Solution {
177-
pub fn rob(nums: Vec<i32>) -> i32 {
178-
let mut f = [0, 0];
179-
for x in nums {
180-
f = [f[0].max(f[1]), f[0] + x];
181-
}
182-
f[0].max(f[1])
183-
}
184-
}
185-
```
186-
187356
<!-- tabs:end -->
188357

189358
<!-- solution:end -->
190359

191360
<!-- solution:start -->
192361

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

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

@@ -264,81 +433,29 @@ function rob(nums: number[]): number {
264433
}
265434
```
266435

267-
#### JavaScript
268-
269-
```js
270-
function rob(nums) {
271-
let [f, g] = [0, 0];
272-
for (const x of nums) {
273-
[f, g] = [Math.max(f, g), f + x];
274-
}
275-
return Math.max(f, g);
276-
}
277-
```
278-
279-
<!-- tabs:end -->
280-
281-
<!-- solution:end -->
282-
283-
<!-- solution:start -->
284-
285-
### Solution 3: Dynamic Programming, top-down approach
286-
287-
<!-- tabs:start -->
288-
289-
#### TypeScript
290-
291-
```ts
292-
export function rob(nums: number[]): number {
293-
const cache: Record<number, number> = {};
294-
const n = nums.length;
295-
let ans = 0;
296-
297-
const dp = (i: number) => {
298-
if (cache[i] !== undefined) return cache[i];
436+
#### Rust
299437

300-
let max = 0;
301-
for (let j = i + 2; j < n; j++) {
302-
max = Math.max(max, dp(j));
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];
303444
}
304-
cache[i] = max + nums[i];
305-
306-
return cache[i];
307-
};
308-
309-
for (let i = 0; i < n; i++) {
310-
ans = Math.max(ans, dp(i));
445+
f[0].max(f[1])
311446
}
312-
313-
return ans;
314447
}
315448
```
316449

317450
#### JavaScript
318451

319452
```js
320-
export function rob(nums) {
321-
const cache = {};
322-
const n = nums.length;
323-
let ans = 0;
324-
325-
const dp = i => {
326-
if (cache[i] !== undefined) return cache[i];
327-
328-
let max = 0;
329-
for (let j = i + 2; j < n; j++) {
330-
max = Math.max(max, dp(j));
331-
}
332-
cache[i] = max + nums[i];
333-
334-
return cache[i];
335-
};
336-
337-
for (let i = 0; i < n; i++) {
338-
ans = Math.max(ans, dp(i));
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];
339457
}
340-
341-
return ans;
458+
return Math.max(f, g);
342459
}
343460
```
344461

0 commit comments

Comments
 (0)