LeetCode 474.一和零 动态规划 一维dp(两个维度)

news2024/11/24 9:56:35

https://leetcode.cn/problems/ones-and-zeroes/description/

给你一个二进制字符串数组 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 。

>>思考和分析

  • x:统计字符串中0的个数总和
  • y:统计字符串中1的个数总和

动规五部曲

1.确定dp数组(dp table)以及下标的含义

        dp[i][j]:最多有 i个'0' 和 j个'1'的 strs的最大子集的大小为dp[i][j]

                       

        dp[i][j]:i个'0' j个'1' 最大背dp[i][j]个 物品

                        

        所求 dp[m][n]

2.确定递推公式

0-1背包的一维dp数组的递推公式:

        dp[j] = max(dp[j],dp[j - weight[i]] + value[i]);

                    ↓将一维度扩展为二维😚

        dp[i][j] = max(dp[i][j],dp[i - x][j - y] + 1);

关键:对比以下,我们就可以得知字符串的 x 和 y相当于物品的重量(weight[i]),字符串本身的个数相当于物品的价值(value[i])

本质:这就是一个典型的01背包问题!!!只不过物品的重量有了两个维度而已(●'~'●)

3.初始化

dp[0][0],非0下标的也初始化为0(因为物品价值不会是负数,初始为0,保证递推的时候dp[i][j]不会被初始值覆盖)

4.确定遍历顺序

在0-1背包中一定是外层for循环遍历物品,内层for循环遍历背包容量且从后向前遍历!

本题中,物品就是strs中的字符串,背包容量就是题目描述中的m 和 n

5.举例推导dp数组

以输入:["10","0001","111001","1","0"],m = 3,n = 3为例

(1)dp数组初始化为如下图,i 和 j 分别表示背包容量的两个维度

(2)遍历字符串数组,获取到"10",我们可以计算出x个"0" 和 y个"1"

然后更新dp数组,推导如下:

dp[3][3] = max(dp[3][3],dp[3-1][3-1] + 1)= max(0,dp[2][2] + 1) = 1

dp[3][2] = max(dp[3][2],dp[3-1][2-1] + 1)= max(0,dp[2][1] + 1) = 1

dp[3][1] = max(dp[3][1],dp[3-1][1-1] + 1)= max(0,dp[2][0] + 1) = 1

------------------------------------------------------------------

dp[2][3] = max(dp[2][3],dp[2-1][3-1] + 1)= max(0,dp[1][2] + 1) = 1

dp[2][2] = max(dp[2][2],dp[2-1][2-1] + 1)= max(0,dp[1][1] + 1) = 1

dp[2][1] = max(dp[2][1],dp[2-1][1-1] + 1)= max(0,dp[1][0] + 1) = 1

------------------------------------------------------------------

dp[1][3] = max(dp[1][3],dp[1-1][3-1] + 1)= max(0,dp[0][2] + 1) = 1

dp[1][2] = max(dp[1][2],dp[1-1][2-1] + 1)= max(0,dp[0][1] + 1) = 1

dp[1][1] = max(dp[1][1],dp[1-1][1-1] + 1)= max(0,dp[0][0] + 1) = 1

(3)遍历字符串数组,获取到"0001",我们可以计算出x个"0" 和 y个"1"

然后更新dp数组,推导如下: 

dp[3][3] = max(dp[3][3],dp[3-3][3-1] + 1)= max(1,dp[0][2] + 1) = 1

dp[3][2] = max(dp[3][2],dp[3-3][2-1] + 1)= max(1,dp[0][1] + 1) = 1

dp[3][1] = max(dp[3][1],dp[3-3][1-1] + 1)= max(1,dp[0][0] + 1) = 1

(4)遍历字符串数组,获取到"111001",我们可以计算出x个"0" 和 y个"1"

我们可以算出x = 2,y = 4,y = 4超出 j 的界限,所以无需要更新

(5)遍历字符串数组,获取到"1",我们可以计算出x个"0" 和 y个"1"

然后更新dp数组,推导如下: 

dp[3][3] = max(dp[3][3],dp[3-0][3-1] + 1)= max(1,dp[3][2] + 1) = 2

dp[3][2] = max(dp[3][2],dp[3-0][2-1] + 1)= max(1,dp[3][1] + 1) = 2

dp[3][1] = max(dp[3][1],dp[3-0][1-1] + 1)= max(1,dp[3][0] + 1) = 1

------------------------------------------------------------------

dp[2][3] = max(dp[2][3],dp[2-0][3-1] + 1)= max(1,dp[2][2] + 1) = 2

dp[2][2] = max(dp[2][2],dp[2-0][2-1] + 1)= max(1,dp[2][1] + 1) = 2

dp[2][1] = max(dp[2][1],dp[2-0][1-1] + 1)= max(1,dp[2][0] + 1) = 1

------------------------------------------------------------------

dp[1][3] = max(dp[1][3],dp[1-0][3-1] + 1)= max(1,dp[1][2] + 1) = 2

dp[1][2] = max(dp[1][2],dp[1-0][2-1] + 1)= max(1,dp[1][1] + 1) = 2

dp[1][1] = max(dp[1][1],dp[1-0][1-1] + 1)= max(1,dp[1][0] + 1) = 1

------------------------------------------------------------------

dp[0][3] = max(dp[0][3],dp[0-0][3-1] + 1)= max(0,dp[0][2] + 1) = 1

dp[0][2] = max(dp[0][2],dp[0-0][2-1] + 1)= max(0,dp[0][1] + 1) = 1

dp[0][1] = max(dp[0][1],dp[0-0][1-1] + 1)= max(0,dp[0][0] + 1) = 1

(6)遍历字符串数组,获取到"0",我们可以计算出x个"0" 和 y个"1"

然后更新dp数组,推导如下: 

dp[3][3] = max(dp[3][3],dp[3-1][3-0] + 1)= max(2,dp[2][3] + 1) = 3

dp[3][2] = max(dp[3][2],dp[3-1][2-0] + 1)= max(2,dp[2][2] + 1) = 3

dp[3][1] = max(dp[3][1],dp[3-1][1-0] + 1)= max(1,dp[2][1] + 1) = 2

dp[3][0] = max(dp[3][0],dp[3-1][0-0] + 1)= max(0,dp[2][0] + 1) = 1

------------------------------------------------------------------

dp[2][3] = max(dp[2][3],dp[2-1][3-0] + 1)= max(2,dp[1][3] + 1) = 3

dp[2][2] = max(dp[2][2],dp[2-1][2-0] + 1)= max(2,dp[1][2] + 1) = 3

dp[2][1] = max(dp[2][1],dp[2-1][1-0] + 1)= max(1,dp[1][1] + 1) = 2

dp[2][0] = max(dp[2][1],dp[2-1][0-0] + 1)= max(0,dp[1][0] + 1) = 1

------------------------------------------------------------------

dp[1][3] = max(dp[1][3],dp[1-1][3-0] + 1)= max(2,dp[0][3] + 1) = 2

dp[1][2] = max(dp[1][2],dp[1-1][2-0] + 1)= max(2,dp[0][2] + 1) = 2

dp[1][1] = max(dp[1][1],dp[1-1][1-0] + 1)= max(1,dp[0][1] + 1) = 2

dp[1][0] = max(dp[1][1],dp[1-1][0-0] + 1)= max(0,dp[0][0] + 1) = 1

(7)获取最终结果dp[m][n] 

完整代码:

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>> dp(m + 1, vector<int> (n + 1, 0)); // 默认初始化0
        for(string str:strs) {// 物品
            int x=0,y=0;
            for(char c:str) {
                if(c == '0') x++;
                else y++;
            }
            for(int i=m;i>=x;i--) { // 背包
                for(int j=n;j>=y;j--) {
                    dp[i][j] = max(dp[i][j],dp[i-x][j-y] + 1);
                }
            }
        }
        return dp[m][n];
    }
};

来自代码随想录的课堂截图

参考和推荐文章、视频:

动态规划之背包问题,装满这个背包最多用多少个物品?| LeetCode:474.一和零_哔哩哔哩_bilibili 代码随想录 (programmercarl.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1043392.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在SpringBoot中利用Redis实现互斥锁

在SpringBoot中利用Redis实现互斥锁 基本知识 前提条件&#xff0c;有一个能够在Springboot中使用Redis的项目&#xff0c;或者能够直接开也行 为什么要实现互斥锁&#xff1a;当我们利用Redis存储热点数据时&#xff0c;突然就过期失效或者被删除了&#xff0c;导致大量请求同…

Flink安装及简单使用

目录 转载处&#xff08;个人用最新1.17.1测试&#xff09; 依赖环境 安装包下载地址 Flink本地模式搭建 安装 启动集群 查看WebUI 停止集群 Flink Standalone搭建 安装 修改flink-conf.yaml配置文件 修改workers文件 复制Flink安装文件到其他服务器 启动集群 查…

秦时明月沧海手游阵容推荐,秦时明月沧海角色强度

秦时明月沧海角色强度如何&#xff1f;在秦时明月沧海手游中&#xff0c;您可以从大量的角色卡牌中选择并发展&#xff0c;为了顺利通过各种副本&#xff0c;玩家们需要精心搭配阵容。那么&#xff0c;具体该如何配置最强的角色呢&#xff1f; 下面&#xff0c;小编将带各位玩家…

简述ceph文件储存系统

Ceph 是一个统一的分布式存储系统和共享机制&#xff0c;它定义了数据如何存储在一个或多个节点上并呈现给其他机器以供文件访问。 Ceph特点 高性能 a. 摒弃了传统的集中式存储元数据寻址的方案&#xff0c;采用CRUSH算法&#xff0c;数据分布均衡&#xff0c;并行度高。 b.考…

Vue - 虚拟DOM的简单理解

目录 虚拟DOM虚拟DOM树生成流程 因为直接操作真实的 DOM 会比较影响效率。所以 vue 使用了 虚拟DOM&#xff08;VNode&#xff09;来描述要渲染的内容。 虚拟DOM 它是一个 js 对象&#xff0c;比如&#xff1a; const vnode {tag: "h1",children: [{ tag: undefi…

【太阳能多电平逆变器】采用SPWM技术的太阳能供电多电平逆变器研究(simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

centos编译安装opencv,生成opencv-2413.jar

文章目录 前言一、问题来源二、编译安装1.下载源码2.安装基础环境3.安装java环境4.编译安装5.查询结果 总结 前言 在centos7的环境中&#xff0c;编译安装opencv&#xff0c;获得libopencv_java2413.so、opencv-2413.jar的库文件和jar包文件 一、问题来源 异常提示&#xff1…

【力扣2154】将找到的值乘以 2

&#x1f451;专栏内容&#xff1a;力扣刷题⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、题目描述二、题目分析 一、题目描述 题目链接&#xff1a;将找到的值乘以 2 给你一个整数数组 nums &#xff0c;另给…

AlienSwap 锋芒初现,NFT 市场或将三分天下

本文仅为资讯分享&#xff0c;不构成任何投资建议&#xff0c;也不推荐您购买、出售或者持有任何加密货币。请读者朋友们 DYOR&#xff0c;理性看待区块链&#xff0c;提高风险意识&#xff0c;谨慎投资&#xff01; ★ Blur 横空出世之前&#xff0c;OpenSea 一直一家独大&am…

一看就会!我把自动化测试框架总结成这样,人人都能学好!

无论是在自动化测试实践&#xff0c;还是日常交流中&#xff0c;经常听到一个词&#xff1a;框架。之前学习自动化测试的过程中&#xff0c;一直对“框架”这个词知其然不知其所以然。 最近看了很多自动化相关的资料&#xff0c;加上自己的一些实践&#xff0c;算是对“框架”…

深入浅出Java的多线程编程——第二篇

目录 前情回顾 1. 中断一个线程 1.1 中断的API 1.2 小结 2. 等待一个线程 2.1 等待的API 3. 线程的状态 3.1 贯彻线程的所有状态 3.2 线程状态和状态转移的意义 4. 多线程带来的的风险-线程安全 (重点) 4.1 观察线程不安全 4.2 线程安全的概念 4.3 线程不安全的原因…

信息安全:网络安全漏洞防护技术原理与应用.

信息安全&#xff1a;网络安全漏洞防护技术原理与应用. 网络安全漏洞又称为脆弱性&#xff0c;简称漏洞。漏洞一般是致使网络信息系统安全策略相冲突的缺陷&#xff0c;这种缺陷通常称为安全隐患。 安全漏洞的影响主要有机密性受损、完整性破坏、可用性降低、抗抵赖性缺失、可…

中睿天下精彩亮相2023国家网络安全宣传周河南省活动

9月11日&#xff0c;2023年国家网络安全宣传周河南省活动正式拉开帷幕&#xff0c;开幕式在八朝古都开封举行。中睿天下受邀参与本次盛会并亮相网络安全产品展&#xff0c;重点展示在网络安全攻击溯源领域的前沿技术、创新方案及实践应用&#xff0c;为与会嘉宾带来了一场独具优…

STL算术生成和集合算法

目录 算术生成算法accumulate 算术生成算法file 常用集合算法 常用集合算法 常用集合算法set_difference 算术生成算法accumulate 算术生成算法属于小型算法&#xff0c;使用时包含的头文件为 include <numeric> accumulate(iterator beg, iterator end, value); …

13:STM32----PWR

目录 一:PWR 1:简历 2:电源框图 3:低功耗模式 4:模式选择 5:低功耗模式注意事项 A:睡眠模式 B:停止模式 C:待机模式 二 : 案例 A:修改主频 1:连接图 2:代码 B:睡眠模式串口发送接收 1:连接图 2:代码 C:停止模式对射式红外传感器计次 1:连接图 2:函数介绍​…

C++入门(前言、命名空间、缺省参数、重载)

该篇博客主要讲述关于C发展前言&#xff0c;以及C祖师爷对C进行改造提升后的新语法进行解释说明&#xff0c;具体内容为&#xff1a;发展历程、命名空间、输入\输出、缺省参数、函数的重载 目录 文章目录 前言 1.什么是C 2.C的发展史 3.关于C的学习 一、关于命名空间 1.含义 2.…

JMeter测试Web服务

Web服务简介 什么是Web服务 【Web服务】即Web Service。Web服务是一种服务导向架构的技术&#xff0c;通过标准的Web协议提供服务&#xff0c;目的是保证不同平台的应用服务可以互操作。根据W3C的定义&#xff0c;Web服务&#xff08;Web service&#xff09;应当是一个软件系统…

ElasticSearch - 基于 “黑马旅游” 案例,实现搜索框、分页、条件过滤、附近酒店、广告置顶功能

目录 一、黑马旅游案例 1.1、实现 搜索框 和 分页 功能 1.1.1、需求分析 a&#xff09;首先搜索框需求 b&#xff09;分页需求 1.1.2、定义实体类 1.1.2、定义 controller 1.1.3、注入 RestHighLevelClient 1.1.4、实现 IHotelService 接口的 search 方法 1.1.5、功能…

【OLSR路由协议】链路状态路由(OLSR)协议中选择多点中继节点算法研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

AIGC 绘画Stable Diffusion工具的安装与使用

我们先让ChatGPT来帮我们回答一下,什么是Stable Diffusion Stable Diffusion 是一种基于概率模型的图像生成技术。它通过对图像空间中每个像素的颜色值进行推断,从而生成具有高度真实感和细节的图像。 Stable Diffusion 使用一种称为扩散过程的方法来生成图像。在生成过程中…