Skip to content

feat: add solutions to lc problem: No.0198 #3249

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
221 changes: 215 additions & 6 deletions solution/0100-0199/0198.House Robber/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,174 @@ tags:

<!-- solution:start -->

### 方法一:动态规划
### 方法一:记忆化搜索

我们设计一个函数 $\textit{dfs}(i)$,表示从第 $i$ 间房屋开始偷窃能够得到的最高金额。那么答案即为 $\textit{dfs}(0)$。

函数 $\textit{dfs}(i)$ 的执行过程如下:

- 如果 $i \ge \textit{len}(\textit{nums})$,表示所有房屋都被考虑过了,直接返回 $0$;
- 否则,考虑偷窃第 $i$ 间房屋,那么 $\textit{dfs}(i) = \textit{nums}[i] + \textit{dfs}(i+2)$;不偷窃第 $i$ 间房屋,那么 $\textit{dfs}(i) = \textit{dfs}(i+1)$。
- 返回 $\max(\textit{nums}[i] + \textit{dfs}(i+2), \textit{dfs}(i+1))$。

为了避免重复计算,我们使用记忆化搜索的方法,将 $\textit{dfs}(i)$ 的结果保存在一个数组或哈希表中,每次计算前先查询是否已经计算过,如果计算过直接返回结果。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是数组长度。

<!-- tabs:start -->

#### Python3

```python
class Solution:
def rob(self, nums: List[int]) -> int:
@cache
def dfs(i: int) -> int:
if i >= len(nums):
return 0
return max(nums[i] + dfs(i + 2), dfs(i + 1))

return dfs(0)
```

#### Java

```java
class Solution {
private Integer[] f;
private int[] nums;

public int rob(int[] nums) {
this.nums = nums;
f = new Integer[nums.length];
return dfs(0);
}

private int dfs(int i) {
if (i >= nums.length) {
return 0;
}
if (f[i] == null) {
f[i] = Math.max(nums[i] + dfs(i + 2), dfs(i + 1));
}
return f[i];
}
}
```

#### C++

```cpp
class Solution {
public:
int rob(vector<int>& nums) {
int n = nums.size();
int f[n];
memset(f, -1, sizeof(f));
auto dfs = [&](auto&& dfs, int i) -> int {
if (i >= n) {
return 0;
}
if (f[i] < 0) {
f[i] = max(nums[i] + dfs(dfs, i + 2), dfs(dfs, i + 1));
}
return f[i];
};
return dfs(dfs, 0);
}
};
```

#### Go

```go
func rob(nums []int) int {
n := len(nums)
f := make([]int, n)
for i := range f {
f[i] = -1
}
var dfs func(int) int
dfs = func(i int) int {
if i >= n {
return 0
}
if f[i] < 0 {
f[i] = max(nums[i]+dfs(i+2), dfs(i+1))
}
return f[i]
}
return dfs(0)
}
```

#### TypeScript

```ts
function rob(nums: number[]): number {
const n = nums.length;
const f: number[] = Array(n).fill(-1);
const dfs = (i: number): number => {
if (i >= n) {
return 0;
}
if (f[i] < 0) {
f[i] = Math.max(nums[i] + dfs(i + 2), dfs(i + 1));
}
return f[i];
};
return dfs(0);
}
```

#### Rust

```rust
impl Solution {
pub fn rob(nums: Vec<i32>) -> i32 {
fn dfs(i: usize, nums: &Vec<i32>, f: &mut Vec<i32>) -> i32 {
if i >= nums.len() {
return 0;
}
if f[i] < 0 {
f[i] = (nums[i] + dfs(i + 2, nums, f)).max(dfs(i + 1, nums, f));
}
f[i]
}

let n = nums.len();
let mut f = vec![-1; n];
dfs(0, &nums, &mut f)
}
}
```

#### JavaScript

```js
function rob(nums) {
const n = nums.length;
const f = Array(n).fill(-1);
const dfs = i => {
if (i >= n) {
return 0;
}
if (f[i] < 0) {
f[i] = Math.max(nums[i] + dfs(i + 2), dfs(i + 1));
}
return f[i];
};
return dfs(0);
}
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- solution:start -->

### 方法二:动态规划

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

Expand Down Expand Up @@ -161,12 +328,28 @@ function rob(nums: number[]): number {
```rust
impl Solution {
pub fn rob(nums: Vec<i32>) -> i32 {
let mut f = [0, 0];
for x in nums {
f = [f[0].max(f[1]), f[0] + x];
let n = nums.len();
let mut f = vec![0; n + 1];
f[1] = nums[0];
for i in 2..=n {
f[i] = f[i - 1].max(f[i - 2] + nums[i - 1]);
}
f[0].max(f[1])
f[n]
}
}
```

#### JavaScript

```js
function rob(nums) {
const n = nums.length;
const f = Array(n + 1).fill(0);
f[1] = nums[0];
for (let i = 2; i <= n; ++i) {
f[i] = Math.max(f[i - 1], f[i - 2] + nums[i - 1]);
}
return f[n];
}
```

Expand All @@ -176,7 +359,7 @@ impl Solution {

<!-- solution:start -->

### 方法二:动态规划(空间优化)
### 方法三:动态规划(空间优化)

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

Expand Down Expand Up @@ -250,6 +433,32 @@ function rob(nums: number[]): number {
}
```

#### Rust

```rust
impl Solution {
pub fn rob(nums: Vec<i32>) -> i32 {
let mut f = [0, 0];
for x in nums {
f = [f[0].max(f[1]), f[0] + x];
}
f[0].max(f[1])
}
}
```

#### JavaScript

```js
function rob(nums) {
let [f, g] = [0, 0];
for (const x of nums) {
[f, g] = [Math.max(f, g), f + x];
}
return Math.max(f, g);
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
Loading
Loading