zoukankan      html  css  js  c++  java
  • LeetCode 474. 一和零

    题目

    分析

    本题是两维01背包。每个子字符串为一件物品,并且只取一次,这就是01背包。两个维度体现在零的数量和一的数量上,也就是原始的01背包中的体积是一个维度,这里对应0的数量和1的数量。原始01背包中的价值对应每一个子字符串,选中子字符串就加1。dp【i】【j】表示最多i个零和最多j个1的最大集合中元素的个数。动态转移方程为:

    dp[i][j] = max(dp[i][j],dp[i-zeroSum][j-oneSum]+1) 这个思想还是来源于01背包中滚动数组的转移方程。dp[i][j]的由来是从上一步来的dp[i][j] (不取这个子串)或者dp[i-zeroSum][j-oneSum]+1(取这个子串)。回顾下用滚动数组优化后的01背包的动态转移方程:dp[j] = max(dp[j], dp[j - weight[i]] + value[i])。其实和本题本质一样,只是本题变成二维。

    滚动数组初始化为0,遍历顺序为:先背包后重量,且重量倒序遍历。

    对应本题:先遍历每个子字符串统计其0和1的数量,然后倒序遍历0和1的数量。

    代码

     1 class Solution {
     2 public:
     3     int findMaxForm(vector<string>& strs, int m, int n) {
     4         vector<vector<int>> dp(m+1,vector<int>(n+1,0));
     5         //外层遍历背包,内层遍历容量
     6         for(auto s:strs){
     7             int zeroSum = 0,oneSum = 0;
     8             for(auto c:s){
     9                 if(c == '0') zeroSum++;
    10                 if(c == '1') oneSum++;
    11             }
    12             for(int i = m;i >= zeroSum;i--){
    13                 for(int j = n;j >=oneSum;j--){
    14                     //不选或者选当前子串
    15                     dp[i][j] = max(dp[i][j],dp[i-zeroSum][j-oneSum]+1);
    16                 }
    17             }
    18         }
    19         return dp[m][n];
    20     }
    21 };
  • 相关阅读:
    关于firstChild,firstElementChild和children
    trim(),正则表达式中文匹配
    Shell之基本用法
    Samba服务部署
    Linux基础(3)
    linux基础(2)
    Linux基础(1)
    网络基础及网络协议
    操作系统简介
    为何要学习计算机基础
  • 原文地址:https://www.cnblogs.com/fresh-coder/p/14404977.html
Copyright © 2011-2022 走看看