代码随想录算法训练营之JAVA|第三十九天|474. 一和零

今天是第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];
    }
}

今日收获

思变,思变,不变则退

你可能感兴趣的:(算法)