-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
98 additions
and
1 deletion.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package main | ||
|
||
/*** | ||
给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 | ||
请你找出并返回 strs 的最大子集的大小,该子集中 最多 有 m 个 0 和 n 个 1 。 | ||
如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。 | ||
---------------------------------------------------------------------------------------------------------- | ||
示例 1: | ||
输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3 | ||
输出:4 | ||
解释:最多有 5 个 0 和 3 个 1 的最大子集是 {"10","0001","1","0"} ,因此答案是 4 。 | ||
其他满足题意但较小的子集包括 {"0001","1"} 和 {"10","1","0"} 。{"111001"} 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。 | ||
---------------------------------------------------------------------------------------------------------- | ||
示例 2: | ||
输入:strs = ["10", "0", "1"], m = 1, n = 1 | ||
输出:2 | ||
解释:最大的子集是 {"0", "1"} ,所以答案是 2 。 | ||
*/ | ||
|
||
|
||
/*** | ||
思路:把总共的 0 和 1 的个数视为背包的容量,每一个字符串视为装进背包的物品。这道题就可以使用 0-1 背包问题的思路完成,这里的目标值是能放进背包的字符串的数量。 | ||
动态规划的思路是:物品一个一个尝试,容量一点一点尝试,每个物品分类讨论的标准是:选与不选。 | ||
定义状态:尝试题目问啥,就把啥定义成状态。dp[i][j][k] 表示输入字符串在子区间 [0, i] 能够使用 j 个 0 和 k 个 1 的字符串的最大数量。 | ||
状态转移方程: | ||
dp[i][j][k]= \begin{cases} dp[i - 1][j][k], & 不选择当前考虑的字符串,至少是这个数值\\ dp[i - 1][j - 当前字符串使用 \;0\; 的个数][k - 当前字符串使用 \;1\; 的个数] + 1 & 选择当前考虑的字符串 \end{cases} | ||
dp[i][j][k]={ | ||
dp[i−1][j][k], | ||
dp[i−1][j−当前字符串使用0的个数][k−当前字符串使用1的个数]+1 | ||
| ||
不选择当前考虑的字符串,至少是这个数值 | ||
选择当前考虑的字符串 | ||
| ||
初始化:为了避免分类讨论,通常多设置一行。这里可以认为,第 00 个字符串是空串。第 00 行默认初始化为 00。 | ||
输出:输出是最后一个状态,即:dp[len][m][n]。 | ||
*/ | ||
|
||
func findMaxForm(strs []string, m int, n int) int { | ||
dp := make([][][]int, len(strs) + 1) | ||
for i := range dp { | ||
dp[i] = make([][]int, m + 1) | ||
for j := range dp[i] { | ||
dp[i][j] = make([]int, n + 1) | ||
} | ||
} | ||
|
||
for i, str := range strs { | ||
zero, one := calZeroAndOne(str) | ||
for j := 0; j <= m; j++ { | ||
for k := 0; k <= n; k++ { | ||
dp[i + 1][j][k] = dp[i][j][k] | ||
if j >= zero && k >= one { | ||
dp[i + 1][j][k] = max(dp[i + 1][j][k], dp[i][j - zero][k - one] + 1) | ||
} | ||
} | ||
} | ||
} | ||
|
||
return dp[len(strs)][m][n] | ||
} | ||
|
||
func calZeroAndOne(num string) (int, int) { | ||
zero := 0 | ||
one := 0 | ||
for _, c := range num { | ||
if c == '0' { | ||
zero++ | ||
} else { | ||
one++ | ||
} | ||
} | ||
return zero, one | ||
} | ||
|
||
func max(lhs, rhs int) int { | ||
if lhs > rhs { | ||
return lhs | ||
} | ||
return rhs | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters