今天是第39天刷leetcode,立个flag,打卡60天。
算法挑战链接
474. 一和零https://leetcode.cn/problems/ones-and-zeroes/
第一想法
题目理解:找到符合条件的子集,这又是一个组合的问题。
看到这个题目的时候,我好像看到了三个维度:物品和背包的两个维度。因此陷入了三维的困境中,以我目前的实力,我是没有办法hold住的。因此我放弃去看题解了。
看完代码随想录之后的想法
依旧是0-1背包问题。看完后的感想是:既然二维的背包问题,可以压缩为一维的,那为啥三维的不能压缩成二维的呢?
动态规划的五部曲走起:
- 确定dp数组(dp table)以及下标的含义
dp[i][j] 代表的含义是:在0-x字符串任取的情况下,满足 最多有 i个 1 和 J个0 的组合有dp[i][j] 种
- 确定递推公式
推导这个值有两个来源:当前的字符串是否需要?
当前字符串不需要:dp[i][j]
当前字符串需要:dp[i-oneNum][j-zoreNum] + 1
因此递推公式是:dp[i][j] = max(dp[i][j], dp[i-oneNum][j-zoreNum] + 1)
- dp的初始化
二维数组全部初始化为0即可,因为后续都会被覆盖的。
- 确定遍历顺序
因为是二维的,因此遍历顺序其实都是可以的。
- 举例推导dp数组
数据就不推导了。
代码如下:
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
//m 是0的个数, n是1的个数
int dp[][] = new int[m+1][n+1];
for (String str : strs) {
int zoreNum = 0;
int oneNum = 0;
for (char c : str.toCharArray()) {
if (c == '0') {
zoreNum++;
}else {
oneNum++;
}
}
for (int i = m; i >= zoreNum; i--) {
for (int j = n; j >= oneNum; j--) {
dp[i][j] = Math.max(dp[i][j], dp[i-zoreNum][j-oneNum] + 1);
}
}
}
return dp[m][n];
}
}
今日收获
思变,思变,不变则退