474.一和零

20 篇文章 2 订阅
15 篇文章 0 订阅
这篇博客讨论了LeetCode第474题《一和零》的解决方法。作者首先尝试使用回溯法,但由于效率问题导致超时。然后,作者介绍了题解中给出的动态规划(DP)解决方案。DP数组dp[i][j][k]表示在前i个字符串中,使用j个0和k个1所能得到的最大子集数量。初始条件和状态转移方程被详细阐述,帮助理解如何找到满足0和1数量限制的最大子集。最后,作者表示代码已省略,暗示完整的实现未在博客中给出。
摘要由CSDN通过智能技术生成

474.一和零

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

示例 1:

输入:strs = [“10”, “0001”, “111001”, “1”, “0”], m = 5, n = 3
输出:4
解释:最多有 5 个 0 和 3 个 1 的最大子集是 {“10”,“0001”,“1”,“0”} ,因此答案是 4 。
其他满足题意但较小的子集包括 {“0001”,“1”} 和 {“10”,“1”,“0”} 。{“111001”} 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。
示例 2:

输入:strs = [“10”, “0”, “1”], m = 1, n = 1
输出:2
解释:最大的子集是 {“0”, “1”} ,所以答案是 2 。

思考

回溯法超时 崩溃!!

package 力扣;

import java.text.BreakIterator;

/**
 * @author yyq
 * @create 2022-06-19 19:00
 */
public class leetcode474 {
    int countZero = 0;
    int countOne = 0;
    int maxlength=0;

    public int findMaxForm(String[] strs, int m, int n) {
        int[][] rec=new int[strs.length][2];
        for (int i = 0; i < strs.length; i++) {
            for (int j = 0; j < strs[i].length(); j++) {
                if(strs[i].charAt(j)=='0'){
                    rec[i][0]++;
                }
                if(strs[i].charAt(j)=='1') {
                    rec[i][1]++;
                }
            }
        }
        int length = 0;
        int startIndex = 0;
        backTracking(startIndex,length,rec,m,n);


        return maxlength;
    }

    private void backTracking(int startIndex, int length, int[][] rec, int m, int n) {
        if(countZero<=m&&countOne<=n){
            if(length>maxlength){
                maxlength = length;
            }

        }
        for (int i=startIndex;i<rec.length;i++){
            if(countZero+rec[i][0]>m||countOne+rec[i][1]>n){
                continue;
            }
            length++;
            countZero = countZero+rec[i][0];
            countOne = countOne+rec[i][1];
            backTracking(i+1,length,rec,m,n);
            length--;
            countZero = countZero-rec[i][0];
            countOne = countOne-rec[i][1];
        }
    }
}


实在没办法 还是看题解吧

leetcode题解如下

dp数组的定义及下标的意义

dp[i][j][k] 表示在前0-i个字符串中,使用了j个0和k个1的情况下最多可以得到的字符串数量。

假设str字符串数组长度为l,最终答案就是 dp[l][m][n]

注意:leetcode题解中i=0代表没有字符串,我感觉不太合适,这里i=0对应着str[0]的字符串

数组初始化

假设第i个字符串的 : 字符’0’的个数为 zeroNum , 字符’1’的个数为 oneNum

当i=0时,对于 dp[i=0][j][k]

if zeroNum>j || oneNum>k

  dp[i=0][j][k] = 0;   

else 

  dp[i=0][j][k] = 1;

当 j=0与k=0时,dp[i][j][k]=0

状态转移方程

假设第i个字符串的 : 字符’0’的个数为 zeroNum , 字符’1’的个数为 oneNum

当 0 和 1 的容量分别是 j 和 k 时,考虑以下两种情况:

  • 如果j<zeroNum || k<oneNum ,不能选第 i 个字符串
    • dp[i][j][k] = dp[i-1][j][k]
  • 如果j≥zeroNum && k≥oneNum
    • 如果不选第i个字符串 ,dp[i][j][k] =dp[i-1][j][k]
    • 如果选第i个字符串,dp[i][j][k] =dp[i-1][j-zeroNum][k-oneNum]+ 1
    • 故 dp[i][j][k] = MAX{dp[i-1][j][k],dp[i-1][j-zeroNum][k-oneNum]+ 1}

代码省略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值