算法系列--动态规划--⼦数组、⼦串系列(数组中连续的⼀段)(1)

💕"我们好像在池塘的水底,从一个月亮走向另一个月亮。"💕
作者:Mylvzi
文章主要内容:算法系列–动态规划–⼦数组、⼦串系列(数组中连续的⼀段)(1)
在这里插入图片描述

大家好,今天为大家带来的是算法系列--动态规划--⼦数组、⼦串系列(数组中连续的⼀段)(1),这是动态规划新的一种题型

1.最⼤⼦数组和

链接:
https://leetcode.cn/problems/maximum-subarray/
分析:

动态规划的子数组问题和前缀和问题是不一样的,

子数组和这道题要求的是子数组和的最大值,我们的状态表示就是记录以i位置为结束的所有子数组的最大和,而前缀和只是一种快速求出区间和的方法,并没有表示最大和这种状态

关于求最大子数组和问题这道题,要注意状态表示的含义以i位置为结尾的所有子数组的最大和,也就是必须以i位置为结尾,那么此时的状态其实只有两种:

  1. 单独一个
  2. 前面的一堆 + 它本身

网上的很多推到状态方程的时候其实很容易让人误解,解释的也不清楚,他们进行状态的分类是根据dp[i - 1]的正负来推导dp[i]的,有的人可能想为什么不判断nums[i]的正负呢?

其实本质都一样,笔者觉得单纯通过形式来推到方程更容易理解一些

子串/子数组问题的一个经验的状态分类就是按照长度分类的,因为他们的状态表示都比较固定,都是以i位置为结束的最大xxxx

有的题目还比较恶心(尤其是关于子串的问题),对于相同的子串有时候还需要去重,就需要额外开一个数组来统计次数

本题的分析思路:
在这里插入图片描述

代码:

class Solution {
    public int maxSubArray(int[] nums) {
        int n = nums.length;
        int dp = 0;
        int max = -0x3f3f3f3f;// 将最大/小值设置为+-ox3f3f3f3f是一种经验

        for(int num : nums) {
            dp = Math.max(num,dp + num);// 填表
            max = Math.max(max,dp);// 更新最值
        }

        return max;
    }
}

2.环形⼦数组的最⼤和

链接:
https://leetcode.cn/problems/maximum-sum-circular-subarray/description/
分析:

本题是上题的一个变种,这里带环了,对于带环的问题,我们最常用的一个做法是想办法将其转化为线性的,对于本题我们可以采用分类讨论的思想

根据什么区分类讨论呢?往往是根据最后结果可能出现的形式去考虑,对于本题,最长的子数组和可能是两种情况

  1. 不带环,在区间内部
  2. 带环,跨越区间

对于情况1,就是最大子数组和的解法,对于情况2,可以转化为求区间内的最小值,那么最大值就是sum - min,最后返回情况1和情况2的最大值即可

下面是详细分析过程

在这里插入图片描述

代码:

class Solution {
    public int maxSubarraySumCircular(int[] nums) {
        // 创建dp表
        int n = nums.length;
        if(n == 1) return nums[0];
        int[] f = new int[n];
        int[] g = new int[n];

        // 初始化
        f[0] = g[0] = nums[0];
        int max = -0x3f3f3f3f;
        int min = 0x3f3f3f3f;
        int sum = nums[0];

        // 填表
        for(int i = 1; i < n; i++) {
            f[i] = Math.max(nums[i],f[i - 1] + nums[i]);
            g[i] = Math.min(nums[i],g[i - 1] + nums[i]);

            max = Math.max(max,f[i]);
            min = Math.min(min,g[i]);

            sum += nums[i];
        }

        // 返回值
        return sum == min ? max : Math.max(max,sum - min);
    }
}

3.乘积最⼤⼦数组

链接:
https://leetcode.cn/problems/maximum-product-subarray/
分析:

首先想到的状态表示就是以i位置为结尾子数组的最大乘积,但是根据这个状态表示去推到状态转移方程时发现只使用一个dp表无法表示所有的情况

  • nums[i] > 0,i位置的状态就是前一个位置的最大乘积 * nums[i]
  • nums[i] < 0,此时无法通过dp[i - 1]来推到dp[i],因为一个负数 * 较大的数一定会变小,那么dp[i]存储的就是以i位置为结尾的子数组的最小乘积,这与我们的状态表示是矛盾的

既然当nums[i] < 0时,需要乘的是以i-1位置为结尾的子数组的最小乘积,那么我们就创建出一个dp表g[i]来表示最小乘积,以下是详细分析过程:
在这里插入图片描述

代码:

class Solution {
    public int maxProduct(int[] nums) {
        // 创建dp表
        int n = nums.length;
        int[] f = new int[n];
        int[] g = new int[n];

        // 初始化
        f[0] = g[0] = nums[0];
        int max = f[0];

        // 填表
        for(int i = 1; i < n; i++) {
            int t1 = 0, t2 = 0;
            if(nums[i] > 0) {
                f[i] = f[i - 1] * nums[i];
                g[i] = g[i - 1] * nums[i];
            }else {
                f[i] = g[i - 1] * nums[i];
                g[i] = f[i - 1] * nums[i];
            }

            f[i] = Math.max(nums[i],f[i]);
            g[i] = Math.min(nums[i],g[i]);

            max = Math.max(f[i],max);
        }

        return max;
    }
}

4.乘积为正数的最⻓⼦数组

链接:
https://leetcode.cn/problems/maximum-length-of-subarray-with-positive-product/description/
分析:

本题相较于上题有两个不同:

  1. 本题要求乘积必须为正数
  2. 本题求解的不是最大的乘积,而是乘积为正数的最长子数组

和上题一样,本题同样需要使用两个dp表来进行状态表示

  • f[i]:以i位置为结尾,乘积为正数的最大子数组长度
  • g[i]:以i位置为结尾,乘积为负数的最大子数组长度

状态转移方程推导如下:

在这里插入图片描述

注意特殊情况:

  • 当n[i] < 0时,f[i] == g[i - 1] + 1,但是如果i位置之前全是正数,此时g[i - 1] == 0,那么f[i] == 0 + 1 = 1了,但是因为n[i] < 0,i位置的f[i]应该等于 0,因为所有的以i位置为结尾的子数组的乘积必然为负数

代码:

class Solution {
    public int getMaxLen(int[] nums) {
        int n = nums.length;
        
        // 1.创建dp表
        int[] f = new int[n];
        int[] g = new int[n];

        // 2.根据状态表示进行初始化
        f[0] = nums[0] > 0 ? 1 : 0;
        g[0] = nums[0] < 0 ? 1 : 0;

        int max = -0x3f3f3f3f;

        // 3.填表
        for(int i = 1; i < n; i++) {
            if(nums[i] > 0) {
                f[i] = f[i - 1] + 1;
                g[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;
            }else if(nums[i] < 0){
                f[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;
                g[i] = f[i - 1] + 1;
            }else {
                f[i] = g[i] = 0;// 注意等于0相当于直接截断 要重新计数 从0开始
            }

            max = Math.max(f[i],max);// 更新长度
        }

        // 处理n == 1的情况
        return max == -0x3f3f3f3f ? f[0] : max;
    }
}

总结:

  • 子数组问题最常用的一种状态表示就是以i位置为结尾的xxxx
  • 在推导状态转移方程时,往往是根据组成子数组的形态来分类讨论(单独一个还是和前面一堆组成子数组)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

插槽和自定义命令

自定义指令 自定义的指令,定义好之后,在标签内使用,当执行new Vue去模板的时候,看到自定义指令,会将下面的函数,等到特定执行Vue实例阶段触发.模板渲染之后.当触发时的传参的参数的第一个是所写的对象的DOM对象,第二个是是包含指令的对象,对象value是指令赋值.当把指令写到标签…

qt生成word文档(wps),代码如下

这是我自己写的&#xff0c;建议往下滑&#xff0c;大佬写的很清楚&#xff0c;我的代码只是人家的一个摘抄部分 链接&#xff1a;https://pan.baidu.com/s/1MgG_dO8hCUi7ErQnOncNOg?pwd1234 提取码&#xff1a;1234使用方法&#xff1a; #include "ExportReport.h&qu…

6个步骤轻松实现 postman 接口压力测试(建议收藏)

这里讲是postman做接口并发测试&#xff0c;基础用法不做赘述 1、第一步接口可以通的情况下点击右上角save 2、将相应信息填入 3、如果是同一个接口修改不同的值如下图 4、点击左上角Runner 5、选择刚才所建接口集合、填入要执行次数 6、查看运行结果 总结&#xff1a; 感谢每…

24计算机考研调剂 | 【官方】湘潭大学

湘潭大学 考研调剂要求 招生专业&#xff1a; 调剂基本要求&#xff1a; &#xff08;1&#xff09;基本要求同《湘潭大学2024年硕士研究生复试录取工作方案》。 &#xff08;2&#xff09;初试成绩要求&#xff1a; 初试成绩各单科均须达到A类考生进入复试的初试成绩基本要…

代码随想录算法训练营第四十六天|139.单词拆分、56. 携带矿石资源(第八期模拟笔试)

139.单词拆分 刷题https://leetcode.cn/problems/word-break/description/文章讲解https://programmercarl.com/0139.%E5%8D%95%E8%AF%8D%E6%8B%86%E5%88%86.html视频讲解https://www.bilibili.com/video/BV1pd4y147Rh/?vd_sourceaf4853e80f89e28094a5fe1e220d9062 题解&…

微服务(基础篇-005-Gateway)

目录 Gateway介绍&#xff1a; 为什么需要网关&#xff08;1&#xff09; gateway快速入门&#xff08;2&#xff09; 断言工厂&#xff08;3&#xff09; 过滤器工厂&#xff08;4&#xff09; 过滤器工厂介绍及案例&#xff08;4.1&#xff09; 默认过滤器&#xff08…

公众号超牛鼻的爆文仿写机器人,原创三篇只需6分钟,篇篇是爆文基因

大家好&#xff0c;我是大胡子&#xff0c;专注于RPA提效​&#xff0c;今天就介绍一款公众号超牛鼻的爆文仿写机器人​。 和以前的公众号爆文机器人不太一样&#xff0c;以前的爆文机器人需要手动插入图片、添加封面、插入话题&#xff0c;然后今天这个机器人就完全解决这几个…

Redission 分布式锁原理分析

一、前言 我们先来说说分布式锁&#xff0c;为啥要有分布式锁呢? 像 JDK 提供的 synchronized、Lock 等实现锁不香吗&#xff1f;这是因为在单进程情况下&#xff0c;多个线程访问同一资源&#xff0c;可以使用 synchronized 和 Lock 实现&#xff1b;在多进程情况下&#xff…

美团面试一面凉经

1.自我介绍 2.科研项目提问 没咋准备&#xff0c;说的有点没逻辑 3.问论坛项目 为什么用Redis实现登录&#xff1f;能不能用其他方式实现&#xff1f; 1、Redis 具备高性能 假如用户第一次访问 MySQL 中的某些数据。这个过程会比较慢&#xff0c;因为是从硬盘上读取的。将…

Jmeter参数化定义和实现

Jmter参数化定义和实现 Jmter参数化参数化本质参数化实现用户定义变量用户参数CSV数据文件设置counter函数 Jmter参数化 参数化本质 使用参数的方式来替代脚本中的固定的测试数据 参数化实现 定义变量&#xff08;最基础&#xff09;文件定义的方式&#xff08;所有测试数据都…

python 读取jpg图片

pillow读取图片 from PIL import Image import numpy as np img_path ./Training/meningioma/M546.jpg # 读取图片 image Image.open(img_path) width, height image.size print("图片的宽度为{},高度为{}".format(width,height)) print("图片的mode为{}&qu…

nginx--解决响应头带Set-Cookie导致的验证失败

解决响应头带Set-Cookie导致的验证失败 前言给nginx.conf 设置Secure配置完成后会发现cookie就不会发生变化了 前言 在用nginx做代理的时候&#xff0c;会发现nginx在访问不同ip请求的时候会带setCookie 导致后端就是放开cookie验证&#xff0c;在访问玩这个链接他更新了cooki…

nandgame中的计算机(Computer)

关卡说明的翻译&#xff1a; 计算机通过组合以下组件来构建一台计算机&#xff1a;一个控制单元 //应该是涵盖了ALU 存储器&#xff08;RAM和寄存器&#xff09; 程序存储单元&#xff08;ROM&#xff09; 一个计数器&#xff0c;用于跟踪当前指令地址&#xff08;称为“程序计…

软件测试/测试开发丨Docker环境安装配置(Mac、Windows、Ubuntu)

macOS 安装 Docker brew cask install docker运行 Docker Ubuntu 安装 Docker # 更新 apt update # 安装依赖 apt install apt-transport-https ca-certificates curl software-properties-common -y # 添加 key curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/…

HTML基础:8个常见表单元素的详解

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端程序媛。 后台回复“前端工具”可免费获取开发工具&#xff0c;持续更新。 今天来说说 HTML 表单。它是用于收集用户输入信息的元素集合。例如文本框、单选按钮、复选框、下拉列表等。 用户经常填写的表…

【保姆级教程】YOLOv8自动数据标注

一、YOLOV8环境准备 1.1 下载安装最新的YOLOv8代码 仓库地址&#xff1a; https://github.com/ultralytics/ultralytics1.2 配置环境 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple1.3 安装labelme标注工具 pip install labelme二、半自动标注…

【操作系统】用户态和内核态

用户态和内核态指的是程序运行时处于状态&#xff0c;在不同时候处于的状态可能会不同。 操作系统为了保护自己而进行严格控制用户资源的访问&#xff0c;不需要外部资源的程序运行状态为用户态&#xff0c;反之需要内核操作资源时为内核态。 用户态到内核态时需要申请外部资源…

Beans模块之工厂模块BeanNameAware

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

【剑指offr--C/C++】JZ23 链表中环的入口结点 与哈希表

一、哈希表&#xff08;unordered_set&#xff09;知识点 unordered_set是一种无序的数据集合容器&#xff0c;元素和键同时存在&#xff0c;元素没有按任何特定的顺序排序&#xff0c;而是根据它们的散列&#xff08;hash&#xff09;值组织成桶&#xff0c;以允许直接通过值…

QT作业day3

1、使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是…