「动态规划」如何求最大子数组和?如何求环形子数组的最大和?

news2024/10/5 19:14:49

53. 最大子数组和icon-default.png?t=N7T8https://leetcode.cn/problems/maximum-subarray/description/

给你一个整数数组nums,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组是数组中的一个连续部分。

  1. 输入:nums = [-2,1,-3,4,-1,2,1,-5,4],输出:6,解释:连续子数组[4,-1,2,1]的和最大,为6。
  2. 输入:nums = [1],输出:1。
  3. 输入:nums = [5,4,-1,7,8],输出:23。

提示:1 <= nums.length <= 10^5,-10^4 <= nums[i] <= 10^4。


我们用动态规划的思想来解决这个问题。

确定状态表示:根据经验和题目要求,我们用dp[i]表示:以i位置为结尾的子数组中的最大和。比如,dp[3]就表示:下标范围是[0, 3],[1, 3],[2, 3],[3, 3]这4个子数组中的最大和。

推导状态转移方程:考虑dp[i],

  • 如果子数组的长度是1,只有下标范围是[i, i]的子数组符合条件,此时的子数组和是nums[i]。
  • 如果子数组的长度大于1,那么以i位置为结尾的子数组中的最大和,就等于以i - 1位置为结尾的子数组中的最大和加上nums[i],即dp[i - 1] + nums[i]。

dp[i]取上面2种情况的较大值,即dp[i] = max(nums[i], dp[i - 1] + nums[i])

初始化:根据状态转移方程,我们需要初始化dp[0]的值。本题中,既可以根据状态表示直接初始化dp[0] = nums[0];也可以在最前面加上一个辅助结点dp[0] = 0,这样max(num[0], dp[0] + nums[0]) = max(nums[0], 0 + nums[0]) = nums[0],和前一种初始化方式等价。这里我们选择后一种方式。

填表顺序:根据状态转移方程,dp[i]依赖于dp[i - 1],所以应从左往右填表

返回值:由于我们并不确定子数组的结尾是那个位置,根据状态表示,我们应返回整个dp表除了辅助结点之外的最大值

细节问题:假设nums有n个元素。由于新增了一个辅助结点,所以dp表的规模是1 x (n + 1),且下标的映射关系为:dp[i]对应nums[i - 1]

时间复杂度:O(N),空间复杂度:O(N)。

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int n = nums.size();

        // 创建dp表
        vector<int> dp(n + 1);

        // 填表
        for (int i = 1; i <= n; i++) {
            dp[i] = max(nums[i - 1], dp[i - 1] + nums[i - 1]);
        }

        // 返回结果
        return *max_element(dp.begin() + 1, dp.end());
    }
};

918. 环形子数组的最大和icon-default.png?t=N7T8https://leetcode.cn/problems/maximum-sum-circular-subarray/description/给定一个长度为n的环形整数数组nums,返回nums的非空子数组的最大可能和。环形数组意味着数组的末端将会与开头相连呈环状。形式上,nums[i]的下一个元素是nums[(i + 1) % n],nums[i]的前一个元素是nums[(i - 1 + n) % n]。子数组最多只能包含固定缓冲区nums中的每个元素一次。形式上,对于子数组nums[i],nums[i + 1],……,nums[j],不存在i <= k1,k2 <= j其中k1 % n == k2 % n。

  1. 输入:nums = [1,-2,3,-2],输出:3,解释:从子数组[3]得到最大和3。
  2. 输入:nums = [5,-3,5],输出:10,解释:从子数组[5,5]得到最大和5 + 5 = 10。
  3. 输入:nums = [3,-2,2,-3],输出:3,解释:从子数组[3]和[3,-2,2]都可以得到最大和3。

提示:n == nums.length,1 <= n <= 3 * 10^4,-3 * 10^4 <= nums[i] <= 3 * 10^4。


环形子数组分为2种情况:

  • 环形子数组不包含首尾相连的部分,也就是说,环形子数组整体位于数组的中央。此时的最大和就是上题中的最大子数组和
  • 环形子数组包含首尾相连的部分,也就是说,环形子数组位于数组的左右两端。此时的最大和等于整个数组的和减去最小子数组和,最小子数组和的求法和上题中的最大子数组和完全类似。

也就是说,只需要求出最大子数组和fmax、最小子数组和gmin以及整个数组的和sum,本题的答案就是max(fmax, sum - gmin)

其中,最小子数组和的求法也是按照上题中动态规划的思路,只需要把状态转移方程中的max改为min,返回结果也从返回最大值改为返回最小值

这里需要注意一个细节问题,如果最终算出来的最小子数组和gmin,整个数组的和sum,满足gmin = sum,此时的sum - gmin = 0,并不表示包含首尾相连部分的环形子数组的最小和是0,因为此时gmin = sum说明最小子数组和是所有元素的和,那么从整个数组中去掉最小子数组和包含的元素后,就啥也不剩了,但是环形子数组中至少包含1个元素,所以这种情况要单独处理一下,如果算出来sum = gmin,那么最终结果就不是max(fmax, sum - gmin),而是直接返回fmax

我们可以用accumulate、max_element和min_element分别完成求和、求最大值、求最小值的操作,也可以在一个循环内手动完成。这里我们选择在一个循环内同时填2个表、求最大值、求最小值以及求和。其中,f表用来求最大子数组和,g表用来求最小子数组和。

时间复杂度:O(N),空间复杂度:O(N)。

class Solution {
public:
    int maxSubarraySumCircular(vector<int>& nums) {
        int n = nums.size(), sum = 0, fmax = INT_MIN, gmin = INT_MAX;

        // 创建dp表
        vector<int> f(n + 1);
        auto g = f;

        // 填表
        for (int i = 1; i <= n; i++) {
            int x = nums[i - 1];
            f[i] = max(x, f[i - 1] + x);
            g[i] = min(x, g[i - 1] + x);
            fmax = max(fmax, f[i]);
            gmin = min(gmin, g[i]);
            sum += x;
        }

        // 返回结果
        return gmin == sum ? fmax : max(fmax, sum - gmin);
    }
};

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

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

相关文章

非线性规划解决工资分配问题

来源&#xff1a;河北工业职业技术大学 安彤彤 彭金杉 张家硕 题目 薪资发放问题 一般公司给职员发放薪金&#xff0c;通常按每月等额发放。某公司即将改进薪金发放方案&#xff0c;允许任职5年以上的职员向公司财务部门申请工资每月可变额度发放&#xff0c;每月工资发放额…

笔记本开机原理

从按下开机键开始&#xff0c;机器是如何开到OS的呢&#xff1f;今天这篇文章和大家极少EC-BIOS-OS的整个开机流程。首先大家要对笔记本的基本架构有所了解&#xff0c;基本架构如下图所示&#xff08;主要组成部分为大写黑体内容&#xff09;。 一、按下PowerButton按钮&#…

css入门宝典

3.1.4 通配符选择器 语法 : *{} 作用 : 让页面中所有的标签执行该样式,通常用来清除间距 例子 : *{ margin: 0; //外间距 padding: 0; //内间距 } 一 CSS基本语法 1基础知识 1.1概述 Css (层叠样式表)是种格式化网页的标准方式&#xff0c; 用于控制设置网页的样式&#xff…

AOP面向切面(方法)编程

AOP面向切面(方法)编程 快速入门&#xff1a;以下示例是计算DeptServiceImpl每一个方法执行的时间 package com.example.aop;import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspec…

springboot集成shardingsphere

导入maven依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spr…

时代巨兽!深度神经网络如何改变我们的世界?

深度神经网络 1、 简介1.1 定义深度神经网络1.2 深度学习的发展历程1.3 深度神经网络的应用领域 2、深度神经网络的基本原理2.1 神经元层2.1.1 神经元2.1.2 神经元层 2.2 前向传播2.3 反向传播2.4 激活函数2.4.1、作用2.4.2、常见激活函数2.4.3、选择激活函数的考虑 2.5 损失函…

Qt QListView自定义树状导航控件

大部分的软件都有多个页面&#xff0c;这时候就需要一个导航栏控件&#xff0c;通过在导航栏中选择某一栏&#xff0c;同时显示对应的页面。 本文代码效果如下&#xff1a; 本文的导航栏控件基于大佬 feiyangqingyun 的导航栏控件博客Qt/C编写自定义控件46-树状导航栏_qt之实现…

24年最新版基础入门大模型辅助Python编程指南

今天这篇文章只会聊 Python 入门基础&#xff0c;如何通过大模型辅助Python 编程&#xff0c;在 后续的文章里慢慢聊。 一点点 python都不会。又想用大模型带飞&#xff0c;辅助 python 编程&#xff0c;提升数据分析能力和效率&#xff0c;怎么办&#xff1f; 一点都不需要担…

Dify源码本地部署启动

背景 Dify是一个开源LLM应用程序开发平台。Dify的直观界面结合了人工智能工作流、RAG管道、代理功能、模型管理、可观察性功能等&#xff0c;让您快速从原型到生产。 Dify提供在线试用功能&#xff0c;可以直接在线体验其功能。同时也支持docker部署&#xff0c;源码部署等方…

C++多线程:生产者消费者模式

文章目录 一、模式简介二、头文件、全局变量2.1 仓库类的设计2.1.1 关于仓库类的分析2.1.2 仓库类的设计代码 2.2 工厂类的设计2.2.1 关于工厂类的分析2.2.2 工厂类的设计代码a 将产品item放到仓库repob 将产品item从仓库repo取出c 生产者操作d 消费者操作 2.2.3 主函数代码 三…

Github 2024-06-14 开源项目日报Top10

根据Github Trendings的统计,今日(2024-06-14统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量JavaScript项目2Python项目2非开发语言项目2TypeScript项目1Dart项目1Rust项目1Lua项目1Java项目1Jupyter Notebook项目1从零开始构建你喜爱的技…

Jira,一个强大灵活的项目和任务管理工具 Python 库

目录 01初识 Jira 为什么选择 Jira? 02安装与配置 安装 jira 库 配置 Jira 访问 获取 API token: 配置 Python 环境: 03基本操作 创建项目 创建任务 查询任务 更新任务 删除任务 04高级操作 处理子任务 搜索任务 添加附件 评论任务 05实战案例 自动化创建…

java:spring actuator扩展原有info endpoint的功能

# 项目代码资源&#xff1a; 可能还在审核中&#xff0c;请等待。。。 https://download.csdn.net/download/chenhz2284/89437506 # 项目代码 【pom.xml】 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId&…

DomoAI让你轻松变身视频达人!支持20s完整视频生成!

账号注册 官网&#xff1a;https://www.domoai.app/zh-Hant/library 功能 支持不同风格的视频类型&#xff0c;支持图片转视频&#xff0c;支持文字转图片&#xff0c;支持静态图片变为动态。 可以切换语言为中文 风格转换 选择不同风格的 支持生成20s&#xff0c;目前接触…

牛客网金九银十最新版互联网Java高级工程师面试八股文出炉!面面俱到,太全了

前言 作为一个 Java 程序员&#xff0c;你平时总是陷在业务开发里&#xff0c;每天噼里啪啦忙敲着代码&#xff0c;上到系统开发&#xff0c;下到 Bug 修改&#xff0c;你感觉自己无所不能。然而偶尔的一次聚会&#xff0c;你听说和自己一起出道的同学早已经年薪 50 万&#x…

IDEA创建web项目

IDEA创建web项目 第一步&#xff1a;创建一个空项目 第二步&#xff1a;在刚刚创建的项目下创建一个子模块 第三步&#xff1a;在子模块中引入web 创建结果如下&#xff1a; 这里我们需要把这个目录移到main目录下&#xff0c;并改名为webapp&#xff0c;结果如下 将pom文件…

贪心算法学习四

例题一 解法&#xff08;暴⼒解法 -> 贪⼼&#xff09;&#xff1a; 暴⼒解法&#xff1a; a. 依次枚举所有的起点&#xff1b; b. 从起点开始&#xff0c;模拟⼀遍加油的流程 贪⼼优化&#xff1a; 我们发现&#xff0c;当从 i 位置出发&#xff0c;⾛了 step 步…

如何在 Windows 上安装 MySQL(保姆级教程2024版)

MySQL 是最流行的数据库管理系统 (DBMS) 之一。它轻量、开源且易于安装和使用&#xff0c;因此对于那些刚开始学习和使用关系数据库的人来说是一个不错的选择。 本文主要系统介绍Windows的环境下MySQL的安装过程和验证过程。 目录 1 安装过程 1.1 前置要求 1.2 下载并安装 …

【three.js】旋转、缩放、平移几何体

目录 一、缩放 二、平移 三、旋转 四、居中 附源码 BufferGeometry通过.scale()、.translate()、.rotateX()、.rotateY()等方法可以对几何体本身进行缩放、平移、旋转,这些方法本质上都是改变几何体的顶点数据。 我们先创建一个平面物体,样子是这样的。 一、缩放 // 几何…

基于Matlab的人脸表情识别系统(GUI界面)【W5】

简介&#xff1a; 该系统是一个基于Matlab开发的人脸表情识别应用程序&#xff0c;旨在识别输入图像中的人脸表情&#xff0c;并通过直观的图形用户界面&#xff08;GUI&#xff09;向用户展示识别结果。系统结合了图像处理、机器学习和用户交互技术&#xff0c;使用户能够轻松…