【每日一题】最大子数组和

news2024/11/13 9:32:08

文章目录

  • Tag
  • 题目来源
  • 题目解读
  • 解题思路
    • 方法一:动态规划
    • 方法二:分治
    • 方法三:前缀和
  • 写在最后

Tag

【动态规划】【前缀和】【数组】【2023-11-20】


题目来源

53. 最大子数组和


题目解读

找出数组 nums 中连续子数组元素和的最大值。数组中的元素范围为 [ − 1 0 4 , 1 0 4 ] [-10^4, 10^4] [104,104],数组长度最大为 1 0 5 10^5 105

进阶:如果你已经成功实现了时间复杂度为 O ( n ) O(n) O(n) 的解法,尝试使用更为精妙的 分治法 求解。


解题思路

方法一:动态规划

状态

dp[i] 表示以第 i 个数结尾的连续子数组的最大和,最后返回的结果为:

m a x 0 < = i < = n − 1 d p [ i ] max_{0<=i<=n-1}{dp[i]} max0<=i<=n1dp[i]

转移关系

以第 i 个数结尾的连续子数组的最大和有这样的转移关系:

d p [ i ] = m a x ( d p [ i − 1 ] + n u m s [ i ] , n u m s [ i ] ) dp[i] = max(dp[i-1] + nums[i], nums[i]) dp[i]=max(dp[i1]+nums[i],nums[i])

base case

由于以第 i 个数结尾的连续子数组的最大和只和上一个状态有关,因此可以使用一个变量 prev 来维护上一个转态的最大子数组和,这样就可以将时间复杂度降低到 O(1)

初始化 prev = 0res = nums[0](表示本次状态的最大值)。

最后返回

最后返回 res

实现代码

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int prev = 0, res = nums[0];
        for (int num : nums) {
            prev = max(prev + num, num);
            res = max(res, prev);
        }
        return res;
    }
};

复杂度分析

时间复杂度: O ( n ) O(n) O(n)

空间复杂度: O ( 1 ) O(1) O(1)


方法二:分治

方法二的计算思想类似于线段树,实质上是分治思想的应用。在线段树中我们可以维护一个区间上的最大元素值、最小元素值以及元素和。本题中使用分治思想解决,我们首先需要解决维护区间上什么样的数据结构。

对于一个区间 [l, r],我们维护四个变量:

  • lSum:表示 [l, r] 内以 l 为左端点的最大子数组和;
  • rSum:表示 [l, r] 内以 r 为右端点的最大子数组和;
  • mSum:表示 [l, r] 内最大子数组和;
  • iSum:表示 [l, r] 的区间和。

区间 [l, r] 上四个变量如何更新呢?

  • iSum 等于左子区间的 lSum 加上右子区间的 rSum,即 iSum = lSum + rSum
  • 区间 [l, r] 上的 lSum 要么等于左子区间 [l, m]lSum,要么等于左子区间 [l, m]iSum 加上右子区间 lSum,二者取较大值;
  • 同理,区间 [l, r] 上的 rSum 要么等于右子区间 [m+1, r]rSum,要么等于右子区间 [m+1, r]rSum 加上左子区间 rSum,二者取较大值;
  • 当计算好上面的三个量之后,就很好计算 [l,r]mSum 了。我们可以考虑 [l,r]mSum 对应的区间是否跨越 m——它可能不跨越 m,也就是说 [l,r]mSum 可能是「左子区间」的 mSum 和 「右子区间」的 mSum 中的一个;它也可能跨越 m,可能是「左子区间」的 rSum 和 「右子区间」的 lSum 求和。三者取最大值。

实现代码

class Solution {
public:
    struct Status {
        int lSum, rSum, mSum, iSum;
    };

    Status pushUp(Status l, Status r) {
        int iSum = l.iSum + r.iSum;
        int lSum = max(l.lSum, l.iSum + r.lSum);
        int rSum = max(r.rSum, r.iSum + l.rSum);
        int mSum = max(max(l.mSum, r.mSum), l.rSum + r.lSum);
        return (Status){lSum, rSum, mSum, iSum};
    }

    Status get(vector<int>&a, int l, int r) {
        if (l == r) {
            return (Status){a[l], a[l], a[l], a[l]};
        }
        int m = (l + r) >> 1;
        Status lSub = get(a, l, m);
        Status rSub = get(a, m+1, r);
        return pushUp(lSub, rSub);
    }

    int maxSubArray(vector<int>& nums) {
        return get(nums, 0, nums.size() - 1).mSum;
    }
};

复杂度分析

时间复杂度:渐进的时间复杂度为 O ( n ) O(n) O(n)

空间复杂度:递归会使用栈空间,空间复杂度为 O ( l o g n ) O(logn) O(logn)

方法三:前缀和

还可以使用前缀和的方法来解决。

我们在遍历数组 nums 时,设当前遍历的元素为 num

  • 更新前缀和 preSum += num
  • 最大子数组和等于当前前缀和减去上次更新的最小前缀和,即 res = max(res, preSum - minPreSum)
  • 更新最小前缀和 minPreSum = min(minPreSum, preSum)

实现代码

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int preSum = 0, minPreSum = 0;
        int res = INT_MIN;
        for (int num : nums) {
            preSum += num;
            res = max(res, preSum - minPreSum);
            minPreSum = min(minPreSum, preSum);
        }
        return res;
    }
};

复杂度分析

时间复杂度: O ( n ) O(n) O(n)

空间复杂度: O ( 1 ) O(1) O(1)


写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。

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

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

相关文章

echarts 实现3D立体柱状图示例

该示例有如下几个特点&#xff1a; ①实现tooltip自定义样式&#xff08;echarts 实现tooltip提示框样式自定义-CSDN博客&#xff09; ②数据为0时&#xff0c;顶部四边形不展示 ③legend图标设置为自定义图片 【第②也是一个难点&#xff0c;我没有找到其他解决办法&#xff…

JZM-D30室温探针台技术参数

概况&#xff1a; JZM-D30室温探针台的诸多设计都是专用的&#xff0c;探针台的配置主要是根据用户的需求进行选配及设计。例如&#xff0c;要求的磁场型号&#xff0c;电源型号&#xff0c;磁场值&#xff0c;样品台的尺寸等&#xff0c;除此之外&#xff0c;该探针台和我司自…

装备中国功勋企业——兰石重装,建设LTC全流程管理|基于得帆云低代码的CRM案例系列

兰石重型装备股份有限公司 兰石重型装备股份有限公司&#xff08;以下简称“兰石重装”&#xff09;成立于2001年&#xff0c;经营范围为炼油、化工、核电等能源领域所需的装备的设计、制造、安装、成套与服务&#xff1b;工程项目建设与服务&#xff1b;机械加工&#xff1b;检…

高版本Vivado和Linux 4.x内核移植Digilent Driver

移植环境 Vivado 2022.2Ubuntu 22.04petalinux 2022.2Linux内核4.14&#xff08;xilinx-linux-2018.3&#xff09;linux-digilent 主要问题 https://github.com/Digilent/linux-digilent 这些驱动支持Linux kernel release 4.x&#xff0c;然而和Vitis 2022.2 套件对应的内核…

Microsoft Visual Studio 2019下载及安装流程记录

第一周任务&#xff1a; 1.笔记本上安装vc2019的环境 2.再把OpenCV安装上 3.根据网上的教程&#xff0c;试着写几个opencv的程序 一、安装Visual Studio 2019社区版 首先先完成安装vc2019的环境&#xff0c; 因为&#xff1a; Microsoft Visual C是用于C编程的工具集合&am…

华为昇腾阿木实验室FMT,开展无人飞艇开发者线下体验活动!

活动背景 气球机器人是一种利用气球作为飞行平台的可编程飞行器&#xff0c;它利用浮力作为主要升力&#xff0c;在灵活性、稳定性和安全性方面展示了巨大的潜力。近年来&#xff0c;这些机器人已在航拍、气象观测、水文学、侦察和特勤等领域发挥了重要作用。 气球机器人是未来…

Chrome中设置安全来源域名

目的&#xff1a; 使得本地映射的域名能被浏览器安全访问&#xff0c;允许调用设备资源 步骤&#xff1a; 在Chrome中导航栏打开 chrome://flags/#unsafely-treat-insecure-origin-as-secure 填入hosts域名&#xff1a;如 http://h5-twzc003.local.com 参考&#xff1a; h…

带哨兵位的单链表

认识 链表分为两种&#xff1a;带头结点的和不带头结点的 之前我们学习了不带哨兵位的单链表&#xff0c;并实现了相关代码 现在我们认识一下带哨兵位头结点的单链表&#xff1a; plist指向带哨兵位的头结点 这个结点不存储有效数据 如果为空链表&#xff1a; 不带头&#…

在Python中调用imageJ开发

文章目录 一、在ImageJ中进行Python开发二、在Python中调用imageJ开发2.1、简介2.2、环境配置2.3、测试一2.4、测试二 Python imageJ 解决方案&#xff0c;采坑记录 一、在ImageJ中进行Python开发 原生ImageJ仅支持JS脚本&#xff08;JAVAScript&#xff09;&#xff0c;而Im…

milvus采坑一:启动服务就会挂掉

原因一 硬盘满了&#xff0c;Eric数据文件存储在硬盘上&#xff0c;当硬盘不足&#xff0c;它就会启动后就挂掉。 此时pymilvus连接一直是timeout。 解决方法&#xff1a;更换存储路径。

在建筑设计方面3DMax和Maya哪一个更好?

对于建筑设计可视化工具&#xff0c;有许多渲染程序提供了一套非常复杂的工具&#xff0c;使专业人员能够做到最好。ArchViz工具对建筑师和设计师来说非常重要&#xff0c;因为它们可以让他们更准确地识别设计发展阶段的问题&#xff0c;并更有效地与客户交流设计理念。 在今天…

AlmaLinux download

前言 一个开源的、社区拥有和管理的、永远免费的企业级Linux发行版&#xff0c;专注于长期稳定性&#xff0c;提供一个健壮的生产级平台。AlmaLinux操作系统是1:1二进制兼容RHEL和pre-Stream CentOS。 AlmaLinux download VersionAlmaLinux downloadAlmaLinux backup阿里云…

代码随想录算法训练营第四十一天【动态规划part03】 | 343. 整数拆分、96.不同的二叉搜索树

343. 整数拆分 题目链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 求解思路&#xff1a; 动规五部曲 确定dp数组及其下标含义&#xff1a;dp[i] 拆分i&#xff0c;可以得到的最大乘积为dp[i]确定递推公式&#xff1a;从1开始遍…

DAY03 类与对象

概述 对象&#xff1a;真实存在的事物 类&#xff1a; 多个对象抽取其共同点形成的概念 静态特征提取出的概念称为成员变量, 又名属性 动态特征提取出的概念称为成员函数, 又名方法 类与对象的关系 在代码中先有类后有对象 一个类可以有多个对象 多个对象可以属于同一个…

同城跑腿服务预约小程序的作用是什么

随着生活质量逐渐提升&#xff0c;围绕人们生活的行业或产品非常多&#xff0c;同时互联网赋能下&#xff0c;也出现了很多便捷人们日常消费的场景&#xff0c;如外卖服务、快递服务等。 跑腿仅依赖微信私聊及电话预约是很低效且容易出错及造成极大工作压力的&#xff0c;同时…

深度学习人体跌倒检测 -yolo 机器视觉 opencv python 计算机竞赛

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习的人体跌倒检测算法研究与实现 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满…

内网穿透的应用-如何在Docker中部署MinIO服务并结合内网穿透实现公网访问本地管理界面

文章目录 前言1. Docker 部署MinIO2. 本地访问MinIO3. Linux安装Cpolar4. 配置MinIO公网地址5. 远程访问MinIO管理界面6. 固定MinIO公网地址 前言 MinIO是一个开源的对象存储服务器&#xff0c;可以在各种环境中运行&#xff0c;例如本地、Docker容器、Kubernetes集群等。它兼…

企业微信机器人定时发送图文信息,后续无需人工操作

企业微信群机器人是企业微信的内置功能&#xff0c;可以理解为是一个群提醒通知工具&#xff0c;接收数据并自动发送信息到企业微信群中。 数环通实现打通定时器和企业微信机器人的对接&#xff0c;定时执行自动化流程&#xff0c;无需人工干预&#xff0c;实现工作流程自动化&…

大型 APP 的性能优化思路

做客户端开发都基本都做过性能优化&#xff0c;比如提升自己所负责的业务的速度或流畅性&#xff0c;优化内存占用等等。但是大部分开发者所做的性能优化可能都是针对中小型 APP 的&#xff0c;大型 APP 的性能优化经验并不会太多&#xff0c;毕竟大型 APP 就只有那么几个&…

UE 材质,如何只取0~1之间的值,其余值抛弃

假如0~1&#xff0c;floor为0&#xff0c;abs为0&#xff0c;Saturate为0&#xff0c;1-x为1&#xff0c;很好 假如1~2&#xff0c;floor为1&#xff0c;abs为1&#xff0c;Saturate为1&#xff0c;1-x为0&#xff0c;很好 假如2~3&#xff0c;floor为2&#xff0c;abs为2&am…