【动态规划三】子数组系列

news2024/11/24 10:59:17

目录

leetcode题目

一、最大子数组和

二、环形子数组的最大和

三、乘积最大子数组

四、乘积为正数的最长子数组长度

五、等差数列划分

六、最长湍流子数组

七、单词拆分

八、环绕字符串中唯一的子字符串


子数组系列,属于线性dp问题,状态表示也是之前提到的以某个位置元素为结尾分析问题,而状态转移方程也是有规律的,一般就是长度为1和长度>1来划分问题,进而得出状态转移方程

leetcode题目

一、最大子数组和

53. 最大子数组和 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/maximum-subarray/1.题目解析

找到和最大的子数组,返回该子数组的和

2.算法分析

1.状态表示

dp[i] 表示 以 i 位置元素为结尾的所有子数组的最大和

2.状态转移方程

3.初始化

添加虚拟节点, 注意下标的映射关系

dp[0] = 0

4.填表

从左向右

5.返回值

dp表中的最大值

3.算法代码

class Solution {
public:
    int maxSubArray(vector<int>& nums)
    {
        //1.创建dp表
        int n = nums.size();
        vector<int> dp(n+1);
        //2.初始化dp表
        dp[0] = 0; //vector默认是0, 可以不写
        //3.填表 + 返回值
        int ret = INT_MIN;
        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;
    }
};

二、环形子数组的最大和

918. 环形子数组的最大和 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/maximum-sum-circular-subarray/description/1.题目解析

与题目一的区别就是本题的数组是环形数组, 因此子数组的选取情况变多了~

2.算法分析

本题的最大子数组和无非两种情况: 第一种情况直接求最大子数组和即可,而第二种情况可以转化成求中间连续部分的最小子数组和~

1.状态表示

f[i]: 以 i 位置为结尾的所有子数组中的最大和

g[i]: 以 i 位置为结尾的所有子数组中的最小和

2.状态转移方程

f[i] = max(nums[i], f[i-1]+nums[i])

g[i] = min(nums[i], g[i-1]+nums[i])

3.初始化

添加虚拟节点, 注意下标的映射关系

dp[0] = 0, g[0] = 0

4.填表

从左向右

5.返回值

①找到f表的最大值 -> fmax

②找到g表的最小值 -> gmin -> sum-gmin

返回①,②两种情况的最大值,但是当数组元素全为负数是有问题的,因此我们需要判断!

sum == gmin ? fmax : max(fmax, sum-gmin)

3.算法代码

class Solution{
public:
    int maxSubarraySumCircular(vector<int>& nums) 
    {
        //1.创建dp表
        int n = nums.size();
        vector<int> f(n+1), g(n+1);
        //2.初始化dp表
        f[0] = 0, g[0] = 0; //vector默认是0, 可以不写
        //3.填表 + 返回值
        int fmax = INT_MIN, gmin = INT_MAX, sum = 0;
        for(int i = 1; i <= n; i++)
        {
            sum += nums[i-1];
            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]);
        }
        return sum == gmin ? fmax : max(fmax, sum-gmin);
    }
};

三、乘积最大子数组

152. 乘积最大子数组 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/maximum-product-subarray/1.题目解析

返回乘积最大的子数组的乘积

2.算法分析

1.状态表示

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

g[i] : 以 i 位置为结尾的所有子数组中的最小乘积

2.状态转移方程

3.初始化

添加虚拟节点, 注意下标的映射关系

f[0] = g[0] = 1

4.填表

从左向右两个表一起填

5.返回值

f表的最大值

3.算法代码

class Solution {
public:
    int maxProduct(vector<int>& nums) 
    {
        //1.创建dp表
        int n = nums.size();
        vector<int> f(n+1), g(n+1);
        //2.初始化dp表
        f[0] = g[0] = 1;
        //3.填表 + 返回值
        int ret = INT_MIN;
        for(int i = 1; i <= n; i++)
        {
            f[i] = max(nums[i-1], max(f[i-1]*nums[i-1], g[i-1]*nums[i-1]));
            g[i] = min(nums[i-1], min(g[i-1]*nums[i-1], f[i-1]*nums[i-1]));
            ret = max(ret, f[i]);
        }
        return ret;
    }
};

四、乘积为正数的最长子数组长度

1567. 乘积为正数的最长子数组长度 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/maximum-length-of-subarray-with-positive-product/description/1.题目解析

求乘积为正数的最长子数组的长度

2.算法分析

1.状态表示

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

2.状态转移方程

3.初始化

添加虚拟节点, 注意下标的映射关系

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

4.填表

从左向右两个表一起填

5.返回值

f表的最大值

3.算法代码

class Solution {
public:
    int getMaxLen(vector<int>& nums)
    {
        //1.创建dp表
        int n = nums.size();
        vector<int> f(n+1), g(n+1);
        //2.初始化dp表
        f[0] = g[0] = 0; //vector默认是0, 可以不写
        //3.填表 + 返回值
        int ret = INT_MIN;
        for(int i = 1; i <= n; i++)
        {
            if(nums[i-1] > 0)
            {
                f[i] = f[i-1] + 1;
                g[i] = g[i-1] == 0 ? 0 : g[i-1] + 1;
            }
            if(nums[i-1] < 0)
            {
                f[i] = g[i-1] == 0 ? 0 : g[i-1] + 1;
                g[i] = f[i-1] + 1;
            }
            ret = max(ret, f[i]);
        }
        return ret;
    }
};

五、等差数列划分

413. 等差数列划分 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/arithmetic-slices/1.题目解析

返回数组中等差数组的个数

2.算法分析

小性质: [a, b, c, d] 是等差数列,[c, d, e]构成等差数列,则[a, b, c, d, e]是等差数列

1.状态表示

dp[i]: 以 i 位置为结尾的所有子数组中等差数列的个数

2.状态转移方程


3.初始化

dp[0] = dp[1] = 0

4.填表

从左向右

5.返回值

返回dp表中所有元素之和

3.算法代码

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums)
    {
        //1.创建dp表
        int n = nums.size();
        vector<int> dp(n);
        //2.初始化
        dp[0] = dp[1] = 0; //vector默认是0, 可以不写
        //3.填表 + 返回值
        int ret = 0;
        for(int i = 2; i < n; i++)
        {
            dp[i] = nums[i] - nums[i-1] == nums[i-1] - nums[i-2] ?  dp[i-1] + 1 : 0;
            ret += dp[i];
        }
        return ret;
    }
};

六、最长湍流子数组

978. 最长湍流子数组 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/longest-turbulent-subarray/1.题目解析

数组中相邻元素对之间的大小关系相反,这就是湍流数组,题目要求返回数组中最长的湍流子数组的长度

2.算法分析

1.状态表示

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

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

2.状态转移方程

3.初始化

把 f 表和 g 表所有的元素都初始化成1

4.填表顺序

从左往右两个表一起填

5.返回值

两个表的最大值

3.算法代码

class Solution {
public:
    int maxTurbulenceSize(vector<int>& arr)
    {
        //1.创建dp表
        int n = arr.size();
        vector<int> f(n, 1), g(n, 1);
        //2.填表 + 返回值
        int ret = 1;
        for(int i = 1; i < n; i++)
        {
            if(arr[i-1] > arr[i])
                g[i] = f[i-1] + 1;
            if(arr[i-1] < arr[i])
                f[i] = g[i-1] + 1;
            ret = max(ret, max(f[i], g[i]));
        }
        return ret;
    }
};

七、单词拆分

139. 单词拆分 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/word-break/1.题目解析

给定一个字符串和单词字典,判断使用字典中的单词(可以重复使用)是否可以拼接成功字符串

2.算法分析

1.状态表示

dp[i]: [0, i]区间内的字符串, 能否被字典中的单词拼接而成

2.状态转移方程

3.初始化

添加虚拟节点

dp[0] = true

下标的映射关系,可以给"原字符串"开始加一个空格, 这样dp表和原始字符串就是一一对应的

4.填表顺序

从左往右

5.返回值

dp[n]

3.算法代码

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) 
    {
        //优化:
        unordered_set<string> hash;
        for(auto& s : wordDict) hash.insert(s);

        //1.创建dp表
        int n = s.size();
        vector<bool> dp(n+1);
        //2.初始化
        dp[0] = true;
        s = ' ' + s;
        //3.填表
        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];
    }
};

八、环绕字符串中唯一的子字符串

467. 环绕字符串中唯一的子字符串 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/unique-substrings-in-wraparound-string/1.题目解析

给定一个base字符串,统计字符串s中有多少个不同的子串在base中出现过

2.算法分析

1.状态表示

dp[i]: 以 i 位置为结尾的所有子串中,有多少个在base中出现过

2.状态转移方程

3.初始化

将dp表里面所有的值都初始化成1, 因此dp[i] += dp[i-1] 即可

4.填表顺序

从左往右

5.返回值

以相同的字符为结尾的所有子串中,可能会出现重复的情况,比如:

"abcyzabc",  该子串中,以第一个字符'c'结尾的子串 abc 与 以第二个字符'c'结尾的子串abc就是重复的,因此我们需要去重(由于以第二个字符'c'结尾的所有子串一定是包含'abc'的,因此同一个字符结尾对应的dp值取最大的即可):

①创建一个大小为26的数组

②里面的值保存相应字符结尾的最大的dp值即可

最后返回 数组中所有元素的和即可

3.算法代码

class Solution {
public:
    int findSubstringInWraproundString(string s) 
    {
        //1.创建dp表
        int n = s.size();
        vector<int> dp(n, 1);
        //2.填表
        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];
        //3.返回值
        int hash[26] = {0};
        for(int i = 0; i < n; i++)
            hash[s[i] - 'a'] = max(hash[s[i] - 'a'], dp[i]);
        int sum = 0;
        for(auto x : hash)
            sum += x;
        return sum;
    }
};

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

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

相关文章

Java实现手机短信验证码(互亿无线)

互亿无线 互亿无线是一家提供电信类增值服务插件以及其他相关插件的公司&#xff0c;是中国移动、中国联通、中国电信三大运营商的战略合作伙伴与工信部认定的电信增值业务服务商。公司旗下运营三大业务平台&#xff1a;数字奖励营销活动平台、应用短信平台、营销短信平台。 官…

阿里开源的lowcode-engine:加速企业级应用开发的低代码利器

lowcode-engine 是阿里巴巴推出的一个企业级的低代码开发平台&#xff0c;它就像是给开发者的一个工具箱&#xff0c;里面装满了各种现成的工具和材料&#xff0c;让搭建应用程序变得像搭积木一样简单。你不需要从零开始&#xff0c;而是可以直接用这些工具和材料去构建你想要的…

AJ-Report开源数据大屏远程命令执行漏洞

文章目录 描述漏洞原理影响版本漏洞复现修复方案 描述 AJ-Report是全开源的一个BI平台&#xff0c;酷炫大屏展示&#xff0c;能随时随地掌控业务动态&#xff0c;让每个决策都有数据支撑。     多数据源支持&#xff0c;内置mysql、elasticsearch、kudu驱动&#xff0c;支持…

STM32单片机实战开发笔记-GPIO控制LED灯、蜂鸣器、继电器等【wulianjishu666】

单片机物联网开发资料&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1XzodQuML7CqZ4ZKinDGKkg?pwdbgep 提取码&#xff1a;bgep 单片机GPIO的Do输出功能 1、功能描述 根据MP3的声音频率&#xff0c;让LED灯以不同的高度&#xff08;LED的多少&#xff09;&#xf…

纯净水20、脉动30被指宰客!疯狂开始反噬小杨哥?

作为疯狂小杨哥早期粉&#xff0c;小柴好像很久没看到小杨哥的搞笑视频了。 自然&#xff0c;再在社交媒体上看到&#xff0c;小杨哥兄弟已经不再是那个青涩的少年了。 而是摇身一变不仅成为一个非常成功带货主播&#xff0c;且成为一个资本版图越来越多&#xff0c;玩的越来越…

AI实景自动无人直播软件:引领直播行业智能化革命;提升直播效果,无人直播软件助力智能讲解

随着科技的快速发展&#xff0c;AI实景自动无人直播软件正在引领直播行业迈向智能化革命。它通过智能讲解、一键开播和智能回复等功能&#xff0c;为商家提供了更高效、便捷的直播体验。此外&#xff0c;软件还支持手机拍摄真实场景或搭建虚拟场景&#xff0c;使直播画面更好看…

阴影渲染在AI去衣技术中的关键作用

引言&#xff1a; 随着人工智能技术的飞速发展&#xff0c;深度学习在图像处理领域取得了突破性的进展。其中&#xff0c;AI去衣技术作为一种高度复杂的图像到图像的转换过程&#xff0c;不仅要求算法能够精确地识别并处理衣物纹理和结构&#xff0c;还要求生成的结果具有高度的…

【C语言】——联合体与枚举

【C语言】——联合体与枚举 一、联合体1.1、联合体类型的声明1.2、联合体的特点1.3、相同成员的结构体和联合体对比1.4、联合体的大小计算1.5、联合体的应用举例 二、枚举2.1、枚举类型的声明2.2、枚举类型的优点 一、联合体 1.1、联合体类型的声明 联合体也叫做共用体   与…

CPLEX+YALMIP安装(matlab调用)

通过百度网盘分享的文件&#xff1a;yalmipc… 链接:https://pan.baidu.com/s/1wwYDu9bHFPmcCg5vD2pSXg?pwd9d1r 提取码:9d1r 复制这段内容打开「百度网盘APP 即可获取」 基于MATLAB的Cplex、Yalmip环境安装_如何安装给matlab安装cplex-CSDN博客 具体安装步骤可以参考这篇博…

模拟实现小米商城(有源码)

项目介绍 这是一个只有前端没有后端的项目, 适合于基础前端课设.该前端项目没有花里胡哨的特效, 纯手写 HTML CSS JS, 特别适合基础小白入门, 或者做为基础的课设(含有组员介绍页面), 此项目中, 充分使用 flex 布局, 绝对 相对定位, css 动画, 封装公共样式区域, 代码风格及命…

使用fitten code插件(vscode),替换通义千问,识别需求中的输入输出

今天我们介绍一个工具,具体介绍可以参考我的这篇文章的介绍,支持vs code 插件,Fitten Code是一款由非十科技开发的AI代码助手,旨在通过大模型驱动来提升编程效率和体验-免费神器-CSDN博客https://blog.csdn.net/lijigang100/article/details/137833223?spm=1001.2014.3001…

图像处理之PCA(C++)

图像处理之PCA&#xff08;C&#xff09; 文章目录 图像处理之PCA&#xff08;C&#xff09;前言一、PCA原理1.原理思想2.实现步骤 二、代码实现总结 前言 在科研、工程应用中&#xff0c;我们往往所获取的数据都包含着很多冗余的信息&#xff0c;这些冗余的信息会对我们分析数…

ubuntu22.04:软件包 wps-office 需要重新安装,但是我无法找到相应的安装文件

错误原因&#xff1a;手动在wps官网上下载的linux deb版本的wps2019,想卸载但是一直报错 解决办法&#xff1a;执行如下命令 sudo rm -rf /var/lib/dpkg/info/wps-office*sudo dpkg --remove --force-remove-reinstreq wps-office 说明&#xff1a; sudo命令是以root执行&…

word文件名和创建时间可以同时提取出来吗?答案是肯定的!方法很简单 一键就搞定

在日常生活和工作中&#xff0c;我们经常需要处理大量的Word文件&#xff0c;有时候需要提取这些文件的文件名以及它们的创建时间。虽然这听起来可能是一个复杂的任务&#xff0c;但实际上&#xff0c;通过一些简单的方法和工具&#xff0c;我们可以轻松地完成这一任务。在本文…

tkinter/python:第一个GUI程序——制作一个数据录入界面

下图是在网上搜寻的一个案例图样&#xff0c;经过了调整修改&#xff0c;登录时界面图如下&#xff1a; 登录后点击百货店铺按钮&#xff0c;界面如下 一、创建root窗口&#xff1a; geometry接收一个字符串&#xff0c;也就是需要建立的窗口尺寸和位置&#xff0c;geometry(…

跨境电商日报:虾皮开设新物流中心;Tk Shop菲律宾调整佣金费率

2024年5月7日跨境电商日报目录&#xff1a; 1.Shopee开设新物流中心&#xff1b; 2.TikTok Shop菲律宾站调整佣金费率&#xff1b; 3.野莓海外仓卖家可以销售9公斤以上商品&#xff1b; 4.亚马逊一季度净销售额同比增长13%&#xff1b; 5.巴西对华二氧化钛启动反倾销调查 …

AIGC (AI-Generated Content) 技术深度探索:现状、挑战与未来愿景

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 &#x1f916; AIGC技术&#xff1a;塑造未来的创意与内容革命 &#x1f31f;引言 &#x1f680;AIGC技术发展现状 &#x1f4c8;核心技术驱动 &#x1f4a1;应用领域拓展 &#x1f310; 面临的挑战 ❌真实性与伦理考量 &am…

王春城:精益变革对于组织的长期发展有什么好处?

众所周知&#xff0c;精益变革不仅仅是一种管理方法的改进&#xff0c;更是一种思维方式的转变&#xff0c;旨在消除浪费、提高效率和持续改进。那么&#xff0c;精益变革对于组织的长期发展究竟有什么好处呢&#xff1f;下面天行健王春城老师将从多个方面详细阐述。 首先&…

怎么制作地图位置二维码?扫码获取地图信息的方法

随着互联网的不断发展&#xff0c;二维码在工作和生活中的应用不断的增多&#xff0c;可以针对不同的用途展示内容。比如现在很多的商家或者店铺会将定位定制生成二维码&#xff0c;印刷到传单或者宣传海报上&#xff0c;就可以让用户通过扫码获取位置&#xff0c;方便精准定位…

MetaCRM upload 任意文件上传漏洞

文章目录 漏洞描述漏洞原理漏洞复现修复建议 漏洞描述 北京美特软件技术有限公司&#xff08;以下简称“美特软件”&#xff09;是一家专业的客户关系管理软件提供商。 美特软件MetaCrm存在文件上传漏洞&#xff0c;攻击者可利用该漏洞上传任意恶意文件。 漏洞原理 在系统u…