markdown复制## 1. 问题背景与理解
今天遇到一道有趣的动态规划题目——LeetCode 474题"一和零"。题目给定一个字符串数组strs和两个整数m、n,要求找出并返回strs的最大子集大小,该子集中最多有m个0和n个1。这道题看似简单,但实际考察了对多维背包问题的理解能力。
我第一次看到题目时,误以为只需要统计所有字符串的0和1数量,然后简单比较即可。但仔细思考后发现,这实际上是一个典型的多维约束条件下的最优解问题。每个字符串相当于一个物品,0和1的数量就是物品的两个"重量"维度,而我们的背包容量就是m和n这两个限制条件。
## 2. 解题思路分析
### 2.1 动态规划状态定义
这道题的核心在于设计合适的状态表示。经过分析,我们需要一个三维数组dp,其中:
- dp[i][j][k] 表示考虑前i个字符串时,使用j个0和k个1能获得的最大子集大小
不过在实际编码中,我们可以优化空间复杂度,使用二维滚动数组:
- dp[j][k] 表示使用j个0和k个1时的最大子集大小
### 2.2 状态转移方程
对于每个字符串,我们需要计算其包含的0和1数量(记作zeros和ones),然后更新dp数组:
```python
for j in range(m, zeros - 1, -1):
for k in range(n, ones - 1, -1):
dp[j][k] = max(dp[j][k], dp[j - zeros][k - ones] + 1)
这个转移方程的意思是:对于每个可能的0和1容量组合,我们比较不选当前字符串和选当前字符串两种情况,取较大值。
3. 完整代码实现
3.1 Python解法
python复制def findMaxForm(strs, m, n):
dp = [[0] * (n + 1) for _ in range(m + 1)]
for s in strs:
zeros = s.count('0')
ones = len(s) - zeros
for j in range(m, zeros - 1, -1):
for k i
