Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
56 changes: 53 additions & 3 deletions solution/0400-0499/0474.Ones and Zeroes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ tags:

时间复杂度 $O(sz \times m \times n)$,空间复杂度 $O(sz \times m \times n)$。其中 $sz$ 是数组 $strs$ 的长度;而 $m$ 和 $n$ 分别是字符串中 $0$ 和 $1$ 的数量上限。

我们注意到 $f[i][j][k]$ 的计算只和 $f[i-1][j][k]$ 以及 $f[i-1][j-a][k-b]$ 有关,因此我们可以去掉第一维,将空间复杂度优化到 $O(m \times n)$。

<!-- tabs:start -->

#### Python3
Expand Down Expand Up @@ -221,13 +219,41 @@ function findMaxForm(strs: string[], m: number, n: number): number {
}
```

#### Rust

```rust
impl Solution {
pub fn find_max_form(strs: Vec<String>, m: i32, n: i32) -> i32 {
let sz = strs.len();
let m = m as usize;
let n = n as usize;
let mut f = vec![vec![vec![0; n + 1]; m + 1]; sz + 1];
for i in 1..=sz {
let a = strs[i - 1].chars().filter(|&c| c == '0').count();
let b = strs[i - 1].len() - a;
for j in 0..=m {
for k in 0..=n {
f[i][j][k] = f[i - 1][j][k];
if j >= a && k >= b {
f[i][j][k] = f[i][j][k].max(f[i - 1][j - a][k - b] + 1);
}
}
}
}
f[sz][m][n] as i32
}
}
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- solution:start -->

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

我们注意到 $f[i][j][k]$ 的计算只和 $f[i-1][j][k]$ 以及 $f[i-1][j-a][k-b]$ 有关,因此我们可以去掉第一维,将空间复杂度优化到 $O(m \times n)$。

<!-- tabs:start -->

Expand Down Expand Up @@ -347,6 +373,30 @@ function findMaxForm(strs: string[], m: number, n: number): number {
}
```

#### Rust

```rust
impl Solution {
pub fn find_max_form(strs: Vec<String>, m: i32, n: i32) -> i32 {
let m = m as usize;
let n = n as usize;
let mut f = vec![vec![0; n + 1]; m + 1];

for s in strs {
let a = s.chars().filter(|&c| c == '0').count();
let b = s.len() - a;
for i in (a..=m).rev() {
for j in (b..=n).rev() {
f[i][j] = f[i][j].max(f[i - a][j - b] + 1);
}
}
}

f[m][n]
}
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
69 changes: 67 additions & 2 deletions solution/0400-0499/0474.Ones and Zeroes/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,20 @@ Other valid but smaller subsets include {&quot;0001&quot;, &quot;1&quot;} and {&

<!-- solution:start -->

### Solution 1
### Solution 1: Dynamic Programming

We define $f[i][j][k]$ as the maximum number of strings that can be obtained from the first $i$ strings using $j$ zeros and $k$ ones. Initially, $f[i][j][k]=0$, and the answer is $f[sz][m][n]$, where $sz$ is the length of the array $strs$.

For $f[i][j][k]$, we have two choices:

- Do not select the $i$-th string, in which case $f[i][j][k]=f[i-1][j][k]$;
- Select the $i$-th string, in which case $f[i][j][k]=f[i-1][j-a][k-b]+1$, where $a$ and $b$ are the number of zeros and ones in the $i$-th string, respectively.

We take the maximum of these two choices to obtain the value of $f[i][j][k]$.

The final answer is $f[sz][m][n]$.

The time complexity is $O(sz \times m \times n)$, and the space complexity is $O(sz \times m \times n)$, where $sz$ is the length of the array $strs$, and $m$ and $n$ are the upper limits on the number of zeros and ones, respectively.

<!-- tabs:start -->

Expand Down Expand Up @@ -203,13 +216,41 @@ function findMaxForm(strs: string[], m: number, n: number): number {
}
```

#### Rust

```rust
impl Solution {
pub fn find_max_form(strs: Vec<String>, m: i32, n: i32) -> i32 {
let sz = strs.len();
let m = m as usize;
let n = n as usize;
let mut f = vec![vec![vec![0; n + 1]; m + 1]; sz + 1];
for i in 1..=sz {
let a = strs[i - 1].chars().filter(|&c| c == '0').count();
let b = strs[i - 1].len() - a;
for j in 0..=m {
for k in 0..=n {
f[i][j][k] = f[i - 1][j][k];
if j >= a && k >= b {
f[i][j][k] = f[i][j][k].max(f[i - 1][j - a][k - b] + 1);
}
}
}
}
f[sz][m][n] as i32
}
}
```

<!-- tabs:end -->

<!-- solution:end -->

<!-- solution:start -->

### Solution 2
### Solution 2: Dynamic Programming (Space Optimization)

We notice that the calculation of $f[i][j][k]$ only depends on $f[i-1][j][k]$ and $f[i-1][j-a][k-b]$. Therefore, we can eliminate the first dimension and optimize the space complexity to $O(m \times n)$.

<!-- tabs:start -->

Expand Down Expand Up @@ -329,6 +370,30 @@ function findMaxForm(strs: string[], m: number, n: number): number {
}
```

#### Rust

```rust
impl Solution {
pub fn find_max_form(strs: Vec<String>, m: i32, n: i32) -> i32 {
let m = m as usize;
let n = n as usize;
let mut f = vec![vec![0; n + 1]; m + 1];

for s in strs {
let a = s.chars().filter(|&c| c == '0').count();
let b = s.len() - a;
for i in (a..=m).rev() {
for j in (b..=n).rev() {
f[i][j] = f[i][j].max(f[i - a][j - b] + 1);
}
}
}

f[m][n]
}
}
```

<!-- tabs:end -->

<!-- solution:end -->
Expand Down
21 changes: 21 additions & 0 deletions solution/0400-0499/0474.Ones and Zeroes/Solution.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
impl Solution {
pub fn find_max_form(strs: Vec<String>, m: i32, n: i32) -> i32 {
let sz = strs.len();
let m = m as usize;
let n = n as usize;
let mut f = vec![vec![vec![0; n + 1]; m + 1]; sz + 1];
for i in 1..=sz {
let a = strs[i - 1].chars().filter(|&c| c == '0').count();
let b = strs[i - 1].len() - a;
for j in 0..=m {
for k in 0..=n {
f[i][j][k] = f[i - 1][j][k];
if j >= a && k >= b {
f[i][j][k] = f[i][j][k].max(f[i - 1][j - a][k - b] + 1);
}
}
}
}
f[sz][m][n] as i32
}
}
19 changes: 19 additions & 0 deletions solution/0400-0499/0474.Ones and Zeroes/Solution2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
impl Solution {
pub fn find_max_form(strs: Vec<String>, m: i32, n: i32) -> i32 {
let m = m as usize;
let n = n as usize;
let mut f = vec![vec![0; n + 1]; m + 1];

for s in strs {
let a = s.chars().filter(|&c| c == '0').count();
let b = s.len() - a;
for i in (a..=m).rev() {
for j in (b..=n).rev() {
f[i][j] = f[i][j].max(f[i - a][j - b] + 1);
}
}
}

f[m][n]
}
}