动态规划算法(子数组专题1)

news2024/11/23 7:21:31

动态规划算法专辑之子数组问题(1)

本专栏将从状态定义、状态转移方程、初始化、填表顺序、返回值这五大细节来详细讲述动态规划的算法的解题思路及代码实现

一、什么是子数组

子数组:子数组是数组中的一个连续部分的集合,子序列可以不连续,但子数组的元素必定在原数组中是连续的

二、最大子数组和

image-20230615060939275

1.题目解析

在n个子数组中,找到和最大的那个,并返回该子数组元素的总和

2.状态定义

根据经验+题目要求,dp[i]表示:以i下标为结尾的子数组中最大的和

3.状态转移方程

这题和最长递增子序列分析相似,dp[i]同样分为长度为1和长度大于1这两种情况

image-20230615194212469

由上诉分析可得如下的状态转移方程:

image-20230615194353900

4.初始化

在之前的子序列问题中,我们是按照长度为1的情况下来对dp表进行初始化,但这题将整个dp表初始化的话,反而冗余了,只需初始化dp[0]即可(在子序列问题中,是和dp表进行比较,此题是和nums进行比较)

5.填表顺序

可以看到在dp表中,i收到i-1的影响,所以应该从左到右进行填表

6.返回值

这和之前的子序列问题也类似,返回的应该是dp表中的最大值

7.代码实现

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int n = nums.size();
        vector<int> dp(n);
        dp[0] = nums[0];
        int res = nums[0];
        for(int i=1;i<n;i++)
        {
            dp[i] = max(dp[i-1] + nums[i],nums[i]);
            res = max(res,dp[i]);
        }

        return res;
    }
};

三、环形子数组的最大和

image-20230615195140108

1.题目解析

本题是上面那题的变形题,将线性的数组,变为了环形,也就是说首尾可以相连,在原题上上升了一定难度

2.状态定义

根据经验+题目要求,dp[i]表示:以下标i结尾的所有环形子数组的和的最大值

状态分析:

image-20230615195923895

由上图我们可以看到,原来的状态定义只能满足下标是连续的状态,对于第二种情况处理起来十分麻烦,在数学上有一种思路:正难则反,既然算收尾相连是麻烦的,除去了首尾相连的子数组,剩下的子数组必然连续,那么就可以复用原来的状态转移方程了,要保证首尾相连最大,数组总和是确定的,所以只需保证剩余子数组和最小

由上述分析,此题因有两个不同且相互独立的子问题,因此要定义两种不同的状态:

f[i]表示:以下标i结尾的所有环形子数组的和的最大值

g[i]表示:以下标i结尾的所有环形子数组的和的最小值

3.状态转移方程

经过上述的分析,状态转移方程也应该有两个:

image-20230615201039604

4.初始化

和上题一样,初始化dp[0]就行

5.填表顺序

经过上述的变形,使得两个dp表中i都只受i-1影响,因此可以从左到右进行填表

试想,如果直接计算首尾相连的情况,还能直接从左到右填表吗?

6.返回值

能直接返回max(fmax,sum - gmin)吗(fmax是f表里的最大值,gmin同理)

很显然是不能的,当数组里的所有元素都为负数时,返回的会是0,全是负数的子数组的和可能出现0吗?

因此,当全负数时,因返回fmax

为了减少单独计算数组总和这一步骤,我们只需在更新dp表的同时计算总和,在最后判断sum和gmin是否相等(详情见代码)

7.代码实现

class Solution {
public:
    int maxSubarraySumCircular(vector<int>& nums) {
        int n = nums.size();
        vector<int> f(n+1,0);
        auto g = f;
        int fmax = INT_MIN;
        int gmin = INT_MAX;
        int sum = 0;
        for(int i=1;i<n+1;i++)
        {
            int x = nums[i-1];
            f[i] = max(x,f[i-1]+x);
            fmax = max(fmax,f[i]);
            g[i] = min(x,g[i-1]+x);
            gmin = min(gmin,g[i]);
            sum += x;
        }
        

        return sum == gmin ? fmax : max(fmax,sum - gmin);
    }
};

四、总结

我们任然不要害怕状态定义,一步一步分析来,当发现无法写出状态转移方程或状态转移方程太难时,我们再重新考虑状态定义即可,没有小白可以一来就能找到最准确的状态转移方程

本文涉及到的几个小细节:对环形问题应该计算他的对立面(正难则反),返回值、初始化

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

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

相关文章

Python+Selenium UI自动化测试环境搭建及使用

目录 一、什么是Selenium &#xff1f; 二、Selenium环境搭建 三、WebDriver API 总结&#xff1a; 一、什么是Selenium &#xff1f; Selenium 是一个浏览器自动化测试框架&#xff0c;它主要用于web应用程序的自动化测试&#xff0c;其主要特点如下&#xff1a;开源、免费…

缅怀(上次写博客是2009年10月24日)

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

Nucleo-F411RE (STM32F411)LL库体验 3 - 滴嗒定时器的配置

Nucleo-F411RE &#xff08;STM32F411&#xff09;LL库体验 3 - 滴嗒定时器的配置 1、LL库延时 LL库初始化时钟的时候调用了LL_Init1msTick(100000000)函数&#xff0c;这个函数其实就是初始化了系统的滴答定时器。 LL_InitTick原型如下&#xff1a; load值 sysclk/1000&a…

RocketMQ架构和工作流程

一.MQ概述 1.简介 MQ&#xff0c;Message Queue&#xff0c;是一种提供消息队列服务的中间件&#xff0c;也称为消息中间件&#xff0c;是一套提供了消息生产、存储、消费全过程API的软件系统。消息即数据。一般消息的体量不会很大。 2.用途 限流削峰 MQ可以将系统的超量请求…

接口测试工具怎么选?这个技巧你一定要知道

目录 前言 一、易用性 二、灵活性 三、可靠性 测试用例 接口测试数据 自动化测试 测试报告 总结 前言 当今软性开发中&#xff0c;接口测试已成为必不可少的一环&#xff0c;该如何选择接口测试工具?选择合适的接口测试工具对于程房员来说非常重要&#xff0c;因为…

SQL死锁

前言&#xff1a; 使用脚本刷数据时&#xff0c;开多线程经常遇到死锁现象&#xff0c;面试也经常问到&#xff0c;故开此篇 日志错误示例&#xff1a; ### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock fo…

Tplink企业版开启ipv6

Tplink企业版开启ipv6 1、登录路由器 路由器的默认地址一般为&#xff1a;192.168.0.1&#xff0c;登录成功后如下图&#xff1a; 2、WAN设置ipv6 wan是设置启用ipv6模式&#xff0c;如果这里无法启用&#xff0c;主要是因为“接口模式”中启用了桥接模式&#xff0c;可以关闭…

多线程详解

多线程详解 Process和Thread 程序是指令和数据的有序结合&#xff0c;其本身没有任何运行的含义&#xff0c;是一个静态的概念 进程是执行程序的一次执行过程&#xff0c;是一个动态的概念&#xff0c;是系统资源分配的单位 通常在一个进程中可以包含若干个线程。线程是CPU调…

(数组) 922. 按奇偶排序数组 II ——【Leetcode每日一题】

❓922. 按奇偶排序数组 II 难度&#xff1a;简单 给定一个非负整数数组 nums&#xff0c; nums 中一半整数是 奇数 &#xff0c;一半整数是 偶数 。 对数组进行排序&#xff0c;以便当 nums[i] 为奇数时&#xff0c;i 也是 奇数 &#xff1b;当 nums[i] 为偶数时&#xff0c…

开发语言的更新换代,都是为了更好地提高生产力,Kotlin也是如此~

作为一名Android开发&#xff0c;学习Kotlin是很有必要的。以下是一些原因&#xff1a; 1.Kotlin是官方支持的语言。 在2017年Google宣布支持Kotlin作为官方开发语言后&#xff0c;Kotlin已成为Android生态系统的重要组成部分。此举表明Kotlin的发展前景非常广阔&#xff0c;…

uniapp兼容多pda扫描扫码

前景 网上有现成的针对单个pda扫码录入的代码&#xff0c;但是公司的需求是在多个不同厂商pda上运行&#xff0c;这就会导致不同的pda默认的广播动作和广播标签不一致的情况&#xff0c;目前也没有获取这俩字段的api。 单个pda扫描扫码代码 先创建一个scanCode.js的文件 le…

UnoCSS给了我一个不用tailwindcss的理由

相同的原由 & 前言 如果你没有听说过 tailwindcss 或者 unocss&#xff0c;请先 return 先去了解一下&#x1f61d;。 开发上&#xff1a;可能为你甚至你们的前端团队节省很多写样式的时间&#xff0c;也能让你或者你们的项目开发体验有很大提升生产上&#xff1a;你们的…

VS2013创建一个MFC工程的步骤

目录 1、新建项目&#xff0c;选择”MFC应用程序“&#xff1b; 2、应用程序类型&#xff0c;选择“基于对话框”&#xff1b; 3、对话框的标题&#xff0c;默认是和项目的名字一致&#xff0c;按需修改&#xff1b; 4、高级功能&#xff0c;可以保持默认&#xff1b; 5、…

一个女测试工程师的大厂日常

今天给大家分享两个朋友的故事&#xff0c;他们分别在国内两家顶尖的互联网大厂&#xff0c;一个在头条&#xff0c;一个在蚂蚁。 头条的故事 头条的主人公&#xff0c;在入职后的一年里&#xff0c;晚上十点半下班是比较早了&#xff0c;基本上都是十一点半左右下班&#xff…

低成本开发专属小程序支持自定义开发设计

传统定制开发小程序成本高&#xff0c;还需要不断地沟通和交流才能一步步地去实现你想要的功能和效果&#xff0c;那么除了传统的定制开发小程序外&#xff0c;用户其实还可以选择使用模板开发小程序&#xff0c;不仅能实现小程序的所有基础功能&#xff0c;还不用编程维护和开…

进程的描述与控制

文章目录 前趋图和程序执行前趋图程序顺序执行程序并发执行 进程引入目的进程的描述进程的定义进程的特征进程的基本状态与转换挂起操作和进程状态的转换挂起操作引入引入挂起操作后进程3个基本状态间的转换引入挂起操作后进程5个基本状态间的转换进程管理中的数据结构OS中用于…

antdb-upgrade大版本升级介绍

antdb-upgrade pg_upgrade 是postgresql 大版本升级的得力工具。 数据库系统数据部分通过 new version的pg_upgrade自动升级完成数据库用户数据部分&#xff0c;主要有两种用法&#xff1a; 使用pg_upgrade copy物理拷贝方式升级(非copy to/copy from逻辑拷贝)。使用pg_upgra…

内网渗透—隧道搭建SPP与NPS内网穿透

内网渗透—隧道搭建&SPP与NPS内网穿透 1. 前言2. SPP2.1. SPP代理通信2.1.1. 服务端配置2.1.2. 客户端配置2.1.3. CS设置2.1.3.1. 设置生成的监听器2.1.3.2. 设置监听的监听器 2.1.4. 执行效果 2.2. SPP隧道建立2.2.1. 服务端设置2.2.2. 客户端配置2.2.3. CS设置2.2.3.1. 设…

Mybatis学习笔记三

目录 一、MyBatis的缓存1.1 MyBatis的一级缓存1.2 MyBatis的二级缓存1.3 二级缓存的相关配置1.4 MyBatis缓存查询的顺序1.5 整合第三方缓存EHCache&#xff08;了解&#xff09; 二、MyBatis的逆向工程2.1 创建逆向工程的步骤2.2 简单使用查询增改 三、 分页插件3.1 分页插件使…

Endnote解决文章题目Title大小写问题,以及专有名词保持全部大写

在写毕业论文或综述类文章时&#xff0c;需要添加大量参考文献&#xff08;100左右或更多&#xff09;&#xff0c;而每个期刊的要求是不一样的&#xff0c;因此手动输入或修改参考文献的格式是愚蠢的&#xff08;狗头保命&#xff09;&#xff0c;所以需要强大的endnote来进行…