474. 一和零--动态规划

Posted hequnwang10

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 。

二、解题

动态规划

strs 数组里的元素就是物品,每个物品都是一个。m 和 n相当于是一个背包,两个维度的背包。
动态规划的步骤:

  1. 确定dp数组以及下标含义:
    dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j];
  2. 递推公式:
    dp[i][j] 可以由前一个strs里的字符串推导出来,strs里的字符串有zero个0,one个1。dp[i][j] 就可以是 dp[i - zero][j - one] + 1。在遍历的过程中,取dp[i][j]的最大值。
    递推公式:dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
  3. dp数组如何初始化:
    物品价值不会是负数,初始为0;
  4. 确定遍历顺序
class Solution 
    public int findMaxForm(String[] strs, int m, int n) 
        if(strs == null || strs.length == 0)
            return 0;
        
        int[][] dp = new int[m+1][n+1];
        for(String str : strs)
            int ones = 0,zeros = 0;
            for(char c : str.toCharArray())
                if(c == '0')
                    zeros++;
                else
                    ones++;
                
            
            for(int i = m;i>=zeros;i--)
                for(int j =n;j>=ones;j--)
                    dp[i][j] = Math.max(dp[i][j],dp[i-zeros][j-ones]+1);
                
            
        
        return dp[m][n];
    

步骤分解
class Solution 
    public int findMaxForm(String[] strs, int m, int n) 
        if(strs == null || strs.length == 0)
            return 0;
        
        int[][] dp = new int[m+1][n+1];
        for(String str : strs)
            int ones = 0,zeros = 0;
            for(char c : str.toCharArray())
                if(c == '0')
                    zeros++;
                else
                    ones++;
                
            
            for(int i = m;i>=zeros;i--)
                for(int j =n;j>=ones;j--)
                    System.out.println("i:"+i+"->j:"+j);
                    System.out.println("pre:"+"dp["+i+"]["+j+"]->"+dp[i][j]+"->"+"dp["+(i-zeros)+"]["+(j-ones)+"]->"+dp[i-zeros][j-ones]);
                    dp[i][j] = Math.max(dp[i][j],dp[i-zeros][j-ones]+1);
                    System.out.println("cur:"+"dp["+i+"]["+j+"]->"+dp[i][j]+"->"+"dp["+(i-zeros)+"]["+(j-ones)+"]->"+dp[i-zeros][j-ones]);
                
            
        
        return dp[m][n];
    

i:1->j:1
pre:dp[1][1]->0->dp[0][0]->0
cur:dp[1][1]->1->dp[0][0]->0
i:1->j:1
pre:dp[1][1]->1->dp[0][1]->0
cur:dp[1][1]->1->dp[0][1]->0
i:1->j:0
pre:dp[1][0]->0->dp[0][0]->0
cur:dp[1][0]->1->dp[0][0]->0
i:1->j:1
pre:dp[1][1]->1->dp[1][0]->1
cur:dp[1][1]->2->dp[1][0]->1
i:0->j:1
pre:dp[0][1]->0->dp[0][0]->0
cur:dp[0][1]->1->dp[0][0]->0

以上是关于474. 一和零--动态规划的主要内容,如果未能解决你的问题,请参考以下文章

[474]. 一和零

474. 一和零--动态规划

Leetcode之动态规划(DP)专题-474. 一和零(Ones and Zeroes)

LeetCode 474 一和零[二进制 动态规划] HERODING的LeetCode之路

leetcode 474. Ones and Zeroes 一和零(中等)

动态规划第七篇:01背包问题(目标和 + 一和零)