题目描述

image.png

解题思路

本题注意区分多重背包和0-1背包。
本题可以抽象为2个背包,0的个数和1的个数分别代表2个维度的背包。

  • 确定dp数组(dp table)以及下标的含义

dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]

  • 确定递推公式

dp[i][j] 可以由前一个strs里的字符串推导出来,strs里的字符串有zeroNum个0,oneNum个1。
dp[i][j] 就可以是 dp[i - zeroNum][j - oneNum] + 1。
zeroNum和oneNum代表重量,而value表示则是字符串本身的个数。

  • dp数组如何初始化

因为物品价值不会是负数,初始为0,保证递推的时候dp[i][j]不会被初始值覆盖。

  • 确定遍历顺序

两个维度遍历,但是背包遍历还是要按照倒序遍历

  • 举例推导dp数组

以输入:[“10”,”0001”,”111001”,”1”,”0”],m = 3,n = 3为例
image.png

  1. public int findMaxForm(String[] strs, int m, int n) {
  2. int[][] dp = new int[m + 1][n + 1];
  3. // 遍历物品
  4. for (String str : strs) {
  5. char[] chars = str.toCharArray();
  6. int zeroNum = 0, oneNums = 0;
  7. for (int i = 0; i < chars.length; i++) {
  8. if (chars[i] == '1') {
  9. oneNums++;
  10. } else {
  11. zeroNum++;
  12. }
  13. }
  14. // 遍历2个背包
  15. for (int i = m; i >= zeroNum; i--) {
  16. for (int j = n; j >= oneNums; j--) {
  17. dp[i][j] = Math.max(dp[i][j], dp[i - zeroNum][j - oneNums] + 1);
  18. }
  19. }
  20. }
  21. return dp[m][n];
  22. }