【动态规划】子数组系列

news2024/11/15 23:40:42

文章目录

  • 动态规划(子数组系列)
    • 1. 最大子数组和
    • 2. 环形子数组的最大和
    • 3. 乘积最大子数组
    • 4. 乘积为正的最长子数组的长度
    • 5. 等差数列划分
    • 6. 最长湍流子数组
    • 7. 单词拆分
    • 8. 环形字符串中的唯一的子字符串

动态规划(子数组系列)

1. 最大子数组和

题目链接

  1. 状态表示

    dp[i]表示到 i 位置时所有子数组的最大和

    如下展示的这样:

    vqwloeygdl-1690446970449.png

  2. 状态转移方程

    image-20230727163820237

  3. 初始化

    为了方便初始化,采用虚拟节点的方式,这里初始化dp[0] = 0

  4. 填表

    从左到右

  5. 返回值

    由于每个dp表里的每个值都表示到这个位置的最大子数组的和,所有需要返回最大值

AC代码:

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

2. 环形子数组的最大和

题目链接

分析题目:这道题目可以取环形数组,是不是可以像之间做的环形的打家劫舍题目一样来解决?

还是分为两种情况来考虑:

image-20230727170118674

如果最大和是蓝色区域的部分,只需要求出最大子数组的和就可以

image-20230727170242287

如果是这样,由于数组整体的和是固定的,只需要求出中间的最小值然后相减即可

  1. 状态表示

    讲过前面的题目分析,发现这个题目需要两个状态表示:

    f[i]表示到 i 位置时所有子数组,子数组和最大的值

    g[i]表示到 i 位置时所有子数组,子数组和最小的值

  2. 状态转移方程

    aj6flq76wn-1690449418341.png

  3. 初始化

    采用虚拟节点的方式

  4. 填表

  5. 返回值

    返回两种情况的较大值

AC代码:

class Solution 
{
public:
    const int N = 0x3f3f3f3f;
    int maxSubarraySumCircular(vector<int>& nums) 
    {
        int n = nums.size();
        vector<int> f(n + 1), g(n + 1);
        int fMax = -N, gMin = N, sum = 0;
        for (int i = 1; i <= n; i++)
        {
            f[i] = max(nums[i - 1], f[i - 1] + nums[i - 1]);
            fMax = max(fMax, f[i]);
            g[i] = min(nums[i - 1], g[i - 1] + nums[i - 1]);
            gMin = min(gMin, g[i]);
            sum += nums[i - 1];
        }
        if (sum == gMin) return fMax;
        else return max(fMax, (sum - gMin));
    }
};

3. 乘积最大子数组

题目链接

  1. 状态表示

    f[i]表示以 i 为结尾所有子数组中最大乘积

    g[i]表示以 i 为结尾所有子数组中最小乘积

  2. 状态转移方程

    iw2g8vi80l-1690451692326.png

  3. 初始化

    虚拟节点的方式,为了不影响后续的填表采用f[0] = 1, g[0] = 1

  4. 填表

    从左到右

  5. 返回值

    返回乘积最大的即可

AC代码:

class Solution 
{
public:
    int maxProduct(vector<int>& nums) 
    {
        int n = nums.size();
        vector<int> f(n + 1), g(n + 1);
        f[0] = g[0] = 1;
        int ret = -0x3f;
        for (int i = 1; i <= n; i++)
        {
            if (nums[i - 1] < 0)
            {
                f[i] = g[i - 1] * nums[i - 1];
                g[i] = f[i - 1] * nums[i - 1];
            }
            if (nums[i - 1] > 0)
            {
                f[i] = f[i - 1] * nums[i - 1];
                g[i] = g[i - 1] * nums[i - 1];
            }
            f[i] = max(nums[i - 1], f[i]);
            g[i] = min(nums[i - 1], g[i]);
            ret = max(ret, f[i]);
        }
        return ret;
    }
};

4. 乘积为正的最长子数组的长度

题目链接

  1. 状态表示

    f[i]表示:以 i 位置为结尾所有子数组中乘积为正数的最大长度

    g[i]表示:以 i 位置为结尾所有子数组中乘积为负数的最大长度

  2. 状态转移方程

    j9nbdlukzq-1690458122443.png

  3. 初始化

    f[0] = 1, g[0] = 0

  4. 填表

  5. 返回值

    返回乘积为正的最大长度

AC代码:

class Solution 
{
public:
    int getMaxLen(vector<int>& nums) 
    {
        int n = nums.size();
        vector<int> f(n + 1), g(n + 1);
        int ret = -0x3f3f3f3f;
        for (int i = 1; i <= n; i++)
        {
            if (nums[i - 1] > 0)
            {
                f[i] = max(1, f[i - 1] + 1);
                g[i] = max(0, g[i - 1] == 0 ? 0 : g[i - 1] + 1);
            }
            if (nums[i - 1] < 0)
            {
                f[i] = max(0, g[i - 1] == 0 ? 0 : g[i - 1] + 1);
                g[i] = max(1, f[i - 1] + 1);
            }
            ret = max(ret, f[i]);
        }
        return ret;
    }
};

5. 等差数列划分

题目链接

  1. 状态表示

    dp[i]表示到 i 位置时,所有是等差数列子数组之和

  2. 状态转移方程

    pgq8pckp7f-1690506578443.png

  3. 初始化

    为了防止后续的填表不越界dp[0] = 0, dp[1] = 0

  4. 填表

    从左到右

  5. 返回值

    dp表的所有元素之和

AC代码:

class Solution 
{
public:
    int numberOfArithmeticSlices(vector<int>& nums) 
    {
        int n = nums.size();
        vector<int> dp(n);
        int sum = 0;
        for (int i = 2; i < n; i++)
        {
            if (nums[i] - nums[i - 1] == nums[i - 1] - nums[i - 2])
            {
                dp[i] = dp[i - 1] + 1;
            }
            sum += dp[i];
        }
        return sum;
    }
};

6. 最长湍流子数组

题目链接

  1. 状态表示

    f[i] 以 i 位置为结尾的所有子数组当中,最后呈现“上升” 状态下最长湍流子数组的长度

    g[i] 以 i 位置为结尾的所有子数组当中,最后呈现“下降”状态下最长湍流子数组的长度

  2. 状态转移方程

    8uo2pl28eh-1690632000050.png

  3. 初始化

    表里的数据都初始化为1

  4. 填表

    从左到右

  5. 返回值

    返回两个表的最大值

AC代码:

class Solution 
{
public:
    int maxTurbulenceSize(vector<int>& arr) 
    {
        int n = arr.size();
        vector<int> f(n, 1), g(n, 1);
        int ret = 1;
        for (int i =1; i < n; i++)
        {
            if (arr[i] > arr[i - 1]) f[i] = g[i - 1] + 1;
            else if (arr[i] < arr[i - 1]) g[i] = f[i - 1] + 1;
            ret = max(ret, max(f[i], g[i]));
        }
        return ret;
    }
};

7. 单词拆分

题目链接

  1. 状态表示

    dp[i] 表示0到i之间的字符串能否被字典拼接

  2. 状态转移方程

    image-20230730124229178

  3. 初始化

    可以在字符串s前面加上一个占位符这样就可以没有下标的映射关系

  4. 填表

    从左到右

  5. 返回值

AC代码:

class Solution 
{
public:
    bool wordBreak(string s, vector<string>& wordDict) 
    {
        unordered_set<string> hash;
        for (auto e : wordDict) hash.insert(e);
        int n = s.size();
        vector<bool> dp(n + 1);
        dp[0] = true;
        s = ' ' + s;
        for (int i = 1; i <= n; i++)
        {
            for (int j = i; j >= 1; j--)
            {
                if (dp[j - 1] && hash.count(s.substr(j, i - j + 1)))
                {
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[n];
    }
};

8. 环形字符串中的唯一的子字符串

题目链接

  1. 状态表示

    dp[i]表示到 i 位置的所有子串当中有多少个在base中出现过

  2. 状态转移方程

    wot5yvg40v-1690694243062.png

  3. 初始化

    初始化为1

  4. 填表

  5. 返回值

    由于dp表当中存的值可能是重复的,所以需要进行去重操作。相同字符串结尾的dp值,取最大的值即可

AC代码:

class Solution 
{
public:
    int findSubstringInWraproundString(string s) 
    {
        int n = s.size();
        vector<int> dp(n, 1);
        for (int i = 1; i < n; i++)
        {
            if ((s[i - 1] + 1 == s[i]) || (s[i - 1] == 'z' && s[i] == 'a'))
            {
                dp[i] = dp[i - 1] + 1;
            }
        }
        int hash[26] = {0};
        int sum = 0;
        for (int i = 0; i < n; i++)
        {
            hash[s[i] - 'a'] = max(hash[s[i] - 'a'], dp[i]);
        }
        for (auto x : hash) sum += x;
        return sum;
    }
};

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

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

相关文章

ETHERCAT转CCLINK网关连接ethercat转换器

你们有没有遇到这样的问题&#xff1f;在生产管理系统中&#xff0c;数据互联互通是非常重要的&#xff0c;但ETHERCAT和CCLINK这两个协议之间的通讯一直是个大问题。今天&#xff0c;我给大家带来了一个好消息——捷米JM-ECT-CCLK&#xff0c;这是一款让各种CCLINK总线和ETHER…

WEB:php_rce

背景知识 Linux命令 thinkPHPv5漏洞 题目 打开页面&#xff0c;页面显示为thinkphp v5的界面&#xff0c;可以判断框架为thinkPHP&#xff0c;可以去网上查找相关的漏洞 由题目可知&#xff0c;php rec是一个通过远程代码执行漏洞来攻击php程序的一种方式 因为不知道是php版…

三数之和——力扣15

文章目录 题目描述法一 双指针排序 题目描述 法一 双指针排序 class Solution{ public:vector<vector<int>> threeSum(vector<int>& nums){int nnums.size();vector<vector<int>> ans;sort(nums.begin(), nums.end());for(int first0;first&…

项目实战 — 消息队列(2){创建核心类}

目录 一、创建项目 二、创建核心类 &#x1f345; 1、 编写交换机类&#xff0c;Exchange &#x1f345; 2、编写存储消息的队列&#xff0c;MSGQueue &#x1f345; 3、编写绑定类&#xff0c;binding &#x1f345; 4、编写消息&#xff0c;Message 一、创建项目 二、创…

【Golang 接口自动化04】 解析接口返回JSON串

目录 前言 解析到结构体 json数据与struct字段是如何相匹配的呢&#xff1f; 解析到interface Go类型和JSON类型 实例代码 simpleJson 总结 资料获取方法 前言 上一次我们一起学习了如何解析接口返回的XML数据&#xff0c;这一次我们一起来学习JSON的解析方法。 JSO…

Mysql 索引失效

1、模糊查询%在前面&#xff0c;无法排序所以失效 2、函数计算 3、表达式计算length(NAME) 4、隐式转换 5、联合索引非最左匹配 6、or 必须都为索引列 事务特性 &#xff08;来自小林coding 事务隔离级别是怎么实现的&#xff1f; | 小林coding (xiaolincoding.com)&#…

基于Open3D的点云处理13-分割

平面分割&#xff08;基于RANSAC&#xff09; 使用RANSAC算法从点云中拟合平面&#xff1b; 接口&#xff1a;segment_plane 测试&#xff1a;Plane-segmentation import open3d as o3dpcd_point_cloud o3d.data.PCDPointCloud() pcd o3d.io.read_point_cloud(pcd_point_cl…

从零开始学Docker(二):启动第一个Docker容器

宿主机环境&#xff1a;RockyLinux 9 这个章节不小心搞成命令学习了&#xff0c;后面在整理成原理吧 Docker生命周期 拉取并启动Nginx容器 # 查找镜像 例如&#xff1a;nginx [root192 ~]# docker search nginx 我们可以看到&#xff0c;第一个时官方认证构建的nginx # 拉…

beego通过gorm访问mysql数据库

一、下载golang 二、解压下载包到C盘 三、配置golang系统环境变量 四、进入新建的工作目录C:\project下载并安装beego 五、将新生成的bee.exe所在的路径c:\project\bin加入到系统变量path里面 六、下载并安装mysql 例如在上图中&#xff0c; 选“No thanks,just start my down…

iOS开发-实现上下翻转轮播循环信息播报效果

iOS开发-实现上下翻转轮播循环信息播报效果 在开发中经常遇到需要实现轮播信息播报&#xff0c;例如以下效果 一、使用UITableView实现展示列表 UITableView 定义UITableView的实例&#xff0c;并让当前视图遵守UITableView的两个协议 property (nonatomic, weak, nullable)…

【Linux多线程】线程的互斥与同步(附抢票案例代码+讲解)

线程的互斥与同步 &#x1f4ab; 概念引入⭐️临界资源&#xff08;Critical Resource&#xff09;&#xff1a;&#x1f31f;临界区&#xff08;Critical Section&#xff09;&#xff1a;✨互斥&#xff08;Mutex&#xff09;&#xff1a; ⚡️结合代码看互斥☄️ 代码逻辑&a…

无涯教程-jQuery - Progressbar组件函数

小部件进度条功能可与JqueryUI中的小部件一起使用。一个简单的进度条显示有关进度的信息。一个简单的进度条如下所示。 Progressbar - 语法 $( "#progressbar" ).progressbar({value: 37 }); Progressbar - 示例 以下是显示进度条用法的简单示例- <!doctype …

appium的基本使用

appium的基本使用 一、appium的基本使用appium环境安装1、安装Android SDK 2、安装Appium3、安装手机模拟器4、Pycharm安装 appium-python-alicent5、连接appium和模拟器6、Python代码调用appium软件&#xff0c;appium软件在通过adb命令调用android操作系统&#xff08;模拟器…

如何在局域网外SSH远程访问连接到家里的树莓派?

文章目录 如何在局域网外SSH远程访问连接到家里的树莓派&#xff1f;如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar4.2 cpolar进行token认证4.3 配置cpol…

详解Mybatis之分页插件【PageHelper】

编译软件&#xff1a;IntelliJ IDEA 2019.2.4 x64 操作系统&#xff1a;win10 x64 位 家庭版 Maven版本&#xff1a;apache-maven-3.6.3 Mybatis版本&#xff1a;3.5.6 文章目录 一. 什么是分页&#xff1f;二. 为什么使用分页&#xff1f;三. 如何设计一个Page类&#xff08;分…

【Python】Web学习笔记_flask(1)——getpost

flask提供的request请求对象可以实现获取url或表单中的字段值 GET请求 从URL中获取name、age两个参数 from flask import Flask,url_for,redirect,requestappFlask(__name__)app.route(/) def index():namerequest.args.get(name)agerequest.args.get(age)messagef姓名:{nam…

玩转LaTeX(四)【文献引入、自命令】

参考文献BibTeX: 使用最原始的文献导入&#xff1a;&#xff08;正文区&#xff09; \begin{document}%参考文献bibtex %一次管理一次使用 %参考文献格式&#xff1a; %\begin{thebibliography}{编号样本} % \bibitem[记号]{引用标志}文献条目1 % \b…

Java 程序员:本是为了跳槽刷完 1000 道真题,想不到被老板知道直接给我升职

同事&#xff1a;前阵子听说你要跳槽&#xff0c;现在准备得怎么样啊&#xff1f; 程序员 T&#xff1a;不跳了 同事&#xff1a;啊&#xff1f;为什么&#xff1f; 程序员 T&#xff1a;涨薪了呗&#xff1f; 同事&#xff1a;真的吗&#xff1f;涨了多少&#xff1f;你自…

IT类技术面试:从小白到高手的进阶指南

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

ElasticSearch基础篇-Java API操作

ElasticSearch基础-Java API操作 演示代码 创建连接 POM依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:sch…