@@ -55,7 +55,174 @@ tags:
55
55
56
56
<!-- solution:start -->
57
57
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
+ ### 方法二:动态规划
59
226
60
227
我们定义 $f[ i] $ 表示前 $i$ 间房屋能偷窃到的最高总金额,初始时 $f[ 0] =0$, $f[ 1] =nums[ 0] $。
61
228
@@ -156,6 +323,22 @@ function rob(nums: number[]): number {
156
323
}
157
324
```
158
325
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
+
159
342
#### JavaScript
160
343
161
344
``` js
@@ -170,27 +353,13 @@ function rob(nums) {
170
353
}
171
354
```
172
355
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
-
187
356
<!-- tabs: end -->
188
357
189
358
<!-- solution: end -->
190
359
191
360
<!-- solution: start -->
192
361
193
- ### 方法二 :动态规划(空间优化)
362
+ ### 方法三 :动态规划(空间优化)
194
363
195
364
我们注意到,当 $i \gt 2$ 时,$f[ i] $ 只和 $f[ i-1] $ 与 $f[ i-2] $ 有关,因此我们可以使用两个变量代替数组,将空间复杂度降到 $O(1)$。
196
365
@@ -264,81 +433,29 @@ function rob(nums: number[]): number {
264
433
}
265
434
```
266
435
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
299
437
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 ];
303
444
}
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 ])
311
446
}
312
-
313
- return ans ;
314
447
}
315
448
```
316
449
317
450
#### JavaScript
318
451
319
452
``` 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];
339
457
}
340
-
341
- return ans;
458
+ return Math .max (f, g);
342
459
}
343
460
```
344
461
0 commit comments