Leetcode - 每日一题(474. 一和零)

原题链接

今天的每日抑题有那么亿点点难,看了半天知道是个动态规划但是没啥头绪 (看来大一学的算法全部扔回去了)。 之后看了[三叶大佬](https://leetcode-cn.com/u/ac_oier/)的题解才明白算法,所以三叶大佬yyds。

思路:已知该题是一个动态规划题,类似于背包问题,只不过这里重物的重量不再是一个维度而是两个维度,价值也恒等于一。由于每个字符串只能被选择一次,因此该题是个01背包问题的变形。

因此我们可以直接套用 01 背包的「状态定义」来做: [ k ] [ i ] [ j ] [k][i][j] [k][i][j] 代表考虑前 k 件物品,在数字 1 容量不超过 i i i,数字 0 容量不超过 j j j 的条件下的「最大价值」(每个字符串的价值均为 1)
则可以得出状态转移方程 f [ k ] [ i ] [ j ] = m a x ( f [ k − 1 ] [ i ] [ j ] , f [ k − 1 ] [ i − c n t [ k ] [ 0 ] ] [ j − c n t [ k ] [ 1 ] ] + 1 ) f[k][i][j]=max(f[k−1][i][j],f[k−1] [i−cnt[k][0]] [j−cnt[k][1]]+1) f[k][i][j]=max(f[k1][i][j],f[k1][icnt[k][0]][jcnt[k][1]]+1)
cnt则为记录0,1 元素出现的次数的数组。

代码如下:

class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        int[][] zeroAndOne = new int[strs.length][2];
		//记录strs每一个元素中0和1出现的次数
        for (int i = 0; i < strs.length; i++) {
            int zeroCnt = 0, oneCnt = 0;
            for (int j = 0; j < strs[i].length(); j++) {
                if (strs[i].charAt(j) == '1') {
                    oneCnt++;
                } else {
                    zeroCnt++;
                }
            }
            zeroAndOne[i][0] = zeroCnt;
            zeroAndOne[i][1] = oneCnt;
        }

		//f数组为动态规划数组
        int[][] f = new int[m + 1][n + 1];
        //滚动数组
        for (int k = 0; k < strs.length; k++) {
            int zero = zeroAndOne[k][0], one = zeroAndOne[k][1];
            //i>=zero,j>=one 确保数组不会越界
            for (int i = m; i >= zero; i--) {
                for (int j = n; j >= one; j--) {
                	//状态转移方程,这里去掉了物品维度
                    f[i][j] = Math.max(f[i][j], f[i - zero][j - one] + 1);
                }
            }
        }
        //返回最终结果
        return f[m][n];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值