当前位置: 首页 > news >正文

编程题-最大子数组和(中等-重点【贪心、动态规划、分治思想的应用】)

题目:

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

子数组是数组中的一个连续部分。

解法一(枚举法-时间复杂度超限):

暴力法,nums的数组元素被重复访问多次,导致时间复杂度超限,仅作为与下面两种方法的对比参考,并不是本题的正确解,时间复杂度为O(n^2)超限,如下为实现代码:

class Solution{
public:int maxSubArray(vector<int> &nums){//类似寻找最大最小值的题目,初始值一定要定义成理论上的最小最大值int max = INT_MIN;int numsSize = int(nums.size());for (int i = 0; i < numsSize; i++){        int sum = 0;for (int j = i; j < numsSize; j++){            sum += nums[j];if (sum > max){max = sum;}}}return max;}
};

解法二(动态规划):

假设nums数组的长度是n,下标从0到n-1。我们用f(i)代表以第i个数结尾的【连续子数组的最大和】,很显然我们要求的答案就是:max(0≤i≤n-1){f(i)}。

因此我们只需要求出每个位置的f(i),然后返回f数组中的最大值即可。那么我们如何求f(i)呢?我们可以考虑nums[i]单独成为一段还是加入f(i-1)对应的那一段,这取决于nums[i]和f(i-1)+nums[i]的大小,我们希望获得一个比较大的,于是可以写出动态规划转移方程:

f(i)=max\left \{ f(i-1)+nums[i], nums[i]\right \}

于是我们可以只用一个变量pre来维护对于当前f(i)的f(i-1)的值是多少。

如果编号为 i 的子问题的结果是负数或者 0 ,那么编号为 i + 1 的子问题就可以把编号为 i 的子问题的结果舍弃掉,而子问题的定义必须以一个数结尾,因此如果子问题 i 的结果是负数或者 0,那么子问题 i + 1 的答案就是以 nums[i] 结尾的那个数。题目只要求返回结果,不要求得到最大的连续子数组是哪一个。这样的问题通常可以使用「动态规划或者贪心算法」解决。如下为实现代码:

class Solution {
public:int maxSubArray(vector<int>& nums) {//pre表示当前f(i)下的f(i-1)的值,初始时pre为0,//maxAns为截止至第i个索引元素时,最大的子数组和,最终的返回值int pre = 0, maxAns = nums[0];for (const auto &x: nums) {pre = max(pre + x, x);maxAns = max(maxAns, pre);}return maxAns;}
};

解法三(分治思想):

我们定义一个操作get(a, l, r)表示查询a序列[l,r]区间内的最大子段和,那么最终要求的答案就是get(nums, 0, nums.size()-1)。如何分治实现这个操作呢?对于一个区间[l,r],我们取m=\left [ \frac{l+r }{2} \right ],对区间[l,m]和[m+1,r]分治求解。当递归逐层深入直到长度缩小为1的时候,递归【开始回升】。这个时候我们考虑如何通过[l,m]区间的信息和[m+1,r]区间的信息合并成区间[l,r]的信息。最关键的两个问题是:

  • 我们要维护区间的哪些信息呢?
  • 我们如何合并这些信息呢?

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

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

以下简称[l,m]为[l,r]的左子区间,[m+1,r]为[l,r]的右子区间 。我们考虑如何维护这些信息呢(如何通过左右子区间的信息合并得到[l,r]的信息)。对于长度为1的区间[i,i],四个量的值都和nums[i]相等。对于长度大于 1 的区间:

1、首先最好维护的是 iSum,区间 [l,r] 的 iSum 就等于【左子区间】的 iSum 加上【右子区间】的 iSum。

2、对于[l,r]的lSum,存在两种可能,它要么等于【左子区间】的lSum,要么等于【左子区间】的lSum加上【右子区间的】lSum,二者取最大。

3、对于[l,r]的rSum,同理,它要么等于【右子区间】的rSum,要么等于【右子区间】的rSum加上【左子区间】的rSum加上右子区间的rSum。

4、当计算好上面的三个量之后,就很好计算[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(logn),这里的总时间相当于遍历这颗二叉树的所有节点,故总时间的渐进上界是 O(\sum_{i=1}^{log(n)}2^{i-1})=O(n),故渐进时间复杂度为 O(n)。空间复杂度:递归会使用 O(logn) 的栈空间,故渐进空间复杂度为 O(logn)。

分治方法相比动态规划(方法二)的优势:它不仅可以解决区间 [0,n−1],还可以用于解决任意的子区间 [l,r] 的问题。如果我们把 [0,n−1] 分治下去出现的所有子区间的信息都用堆式存储的方式记忆化下来,即建成一棵真正的树之后,我们就可以在 O(logn) 的时间内求到任意区间内的答案,我们甚至可以修改序列中的值,做一些简单的维护,之后仍然可以在 O(logn) 的时间内求到任意区间内的答案,对于大规模查询的情况下,这种方法的优势便体现了出来。这棵树就是上文提及的一种神奇的数据结构——线段树。

笔者小记:

1、动态规划与分治法和贪心法类似,都是将问题分解为更小的子问题,并通过求解子问题来得到全局最优解。然而,它们在处理子问题的方式上有所不同:

  • 贪心法‌:当前选择依赖于已经作出的所有选择,但不依赖于有待于做出的选择和子问题。它自顶向下,一步一步地作出贪心选择。
  • 分治法‌:各个子问题是独立的,一旦递归地求出各子问题的解后,自下而上地将子问题的解合并成问题的解。
  • 动态规划‌:允许子问题不独立,通过自身子问题的解作出选择,对每一个子问题只解一次,并将结果保存起来,避免每次碰到时都要重复计算‌。

解决问题的时候,应根据题目要求划分采用贪心思想、动态规划思想、分治思想三类思想的哪类问题,再进行代码的实现,三种思想时间复杂度都较低,单层循环逻辑可实现。

相关文章:

编程题-最大子数组和(中等-重点【贪心、动态规划、分治思想的应用】)

题目&#xff1a; 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组是数组中的一个连续部分。 解法一&#xff08;枚举法-时间复杂度超限&#xff09;&#xff1a; …...

阿里云视频点播,基于thinkphp8上传视频

前端参考官方示例(jQuery版) <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>阿里云 JavaScript上传SDK Demo (使用jquery)</title><script src"__STATIC__/jquery.min.js"></script><sc…...

《探秘AI绿色计算:降低人工智能硬件能耗的热点技术》

在人工智能飞速发展的当下&#xff0c;其硬件能耗问题愈发凸显。据国际能源署预测&#xff0c;人工智能的能源消耗可能大幅增长。因此&#xff0c;降低人工智能硬件能耗&#xff0c;实现绿色计算&#xff0c;已成为行业关键课题。以下是一些正在崭露头角的热点技术。 新型硬件…...

神经网络常见激活函数 9-CELU函数

文章目录 CELU函数导函数函数和导函数图像优缺点pytorch中的CELU函数tensorflow 中的CELU函数 CELU 连续可微指数线性单元&#xff1a;CELU&#xff08;Continuously Differentiable Exponential Linear Unit&#xff09;,是一种连续可导的激活函数&#xff0c;结合了 ELU 和 …...

软考高级《系统架构设计师》知识点(四)

嵌入式技术 第二版新增内容 嵌入式系统&#xff1a;以应用为中心、以计算机技术为基础&#xff0c;并将可配置与可裁减的软、硬件、集成于一体的专用计算机系统&#xff0c;需要满足应用对功能、可靠性、成本、体积和功耗等方面的严格要求。一般嵌入式系统由嵌入式处理器、相关…...

opencv交叉编译

适用于瑞芯微&#xff0c;海思&#xff0c;酷芯等ARM平台。采用编译脚本配置编译选项&#xff0c;方便编译。 目录 一、创建目录 二、工具链配置 三、编译脚本 四、编译 一、创建目录 mikemike-virtual-machine:opencv-4.12/opencv/opencv$ tree . -L 1 . ├── 3rdpart…...

安装vite报错Install for [ ‘create-vite@latest‘ ] failed with code 1

报错内容&#xff1a; npm ERR! code ENOLOCAL npm ERR! Could not install from “Files\nodejs\node_cache_npx\31400” as it does not contain a package.json file. npm ERR! A complete log of this run can be found in: npm ERR! D:\Program Files\nodejs\node_cache_…...

Spring框架中都用到了哪些设计模式?

大家好&#xff0c;我是锋哥。今天分享关于【Spring框架中都用到了哪些设计模式&#xff1f;】面试题。希望对大家有帮助&#xff1b; Spring框架中都用到了哪些设计模式&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Spring框架中使用了大量的设计模…...

LabVIEW 中 dotnet.llb 库功能

在 LabVIEW 功能体系里&#xff0c;位于 C:\Program Files (x86)\National Instruments\LabVIEW 2019\vi.lib\Platform\dotnet.llb 路径下的 dotnet.llb 库意义重大。作为与 .NET 技术交互的关键库&#xff0c;它使 LabVIEW 用户能够与基于 .NET 框架开发的应用程序和组件进行交…...

C# 变量,字段和属性的区别

总目录 前言 在C#中&#xff0c;变量&#xff08;Variables&#xff09;、字段&#xff08;Fields&#xff09; 和 属性&#xff08;Properties&#xff09; 是三个容易混淆但作用截然不同的概念。以下是它们的核心区别与使用场景&#xff1a; 一、变量&#xff08;Variables&…...

wordpress模板文件结构超详解

wordpress网站建设中&#xff0c;主题的制作是最为核心的环节。了解模板文件结构是模板制作的第一步&#xff0c;本文所讲的模板文件结构包括两部分&#xff0c;一是指以文件名为概念的文件结构&#xff0c;二是指文件内容的代码结构。 一、如何使模板文件起作用 ↑ wordpres…...

android studio下载安装汉化-Flutter安装

1、下载android studio官方地址&#xff1a;&#xff08;这个网址可能直接打不开&#xff0c;需要VPN&#xff09; https://developer.android.com/studio?hlzh-cn mac版本分为X86和arm版本&#xff0c;电脑显示芯片是Inter的就是x86的&#xff0c;显示m1和m2的就是arm的 …...

数据开放共享和平台整合优化取得实质性突破的智慧物流开源了

智慧物流视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本可通过边缘计算技术…...

如何设置 Nginx 连接超时并进行测试(Nginx优化)

&#x1f3e1;作者主页&#xff1a;点击&#xff01; Nginx-从零开始的服务器之旅专栏&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年2月15日14点22分 在高并发场景下&#xff0c;如…...

springboot整合mybatis-plus(保姆教学) 及搭建项目

一、Spring整合MyBatis (1)将MyBatis的DataSource交给Spring IoC容器创建并管理&#xff0c;使用第三方数据库连接池(Druid&#xff0c;C3P0等)代替MyBatis内置的数据库连接池 (2)将MyBatis的SqlSessionFactory交给Spring IoC容器创建并管理&#xff0c;使用spring-mybatis整…...

知识管理成功:关键指标和策略,研究信息的投资回报率

信息过载会影响生产力。没有人工智能的帮助&#xff0c;信息过载会影响生产力。大量的可用信息&#xff0c;知识工作者不仅仅是超负荷工作&#xff1b;他们感到不知所措&#xff0c;他们倾向于浪费时间&#xff08;和脑细胞&#xff09;来应付他们被大量的数据抛向他们&#xf…...

【算法】链表

零&#xff1a;链表常用技巧 1&#xff1a;引入虚拟头结点 &#xff08;1&#xff09;便于处理边界情况 &#xff08;2&#xff09;方便我们对链表操作 2&#xff1a;两步尾插&#xff0c;头插 &#xff08;1&#xff09;尾插 tail指向最后一个节点&#xff0c;tail.next…...

集成测试总结文档

1. 集成测试的定义 集成测试&#xff08;Integration Testing&#xff09;是在单元测试之后&#xff0c;将多个独立的软件模块或组件组合在一起进行测试的过程&#xff0c;目的是验证这些模块之间的接口、数据传递、协作逻辑是否符合设计要求&#xff0c;并发现因集成引发的缺…...

关于Dest1ny:我的创作纪念日

Dest1ny 因为这是csdn任务&#xff0c;我就稍微“写”了一下&#xff01; 如果大家真的有什么想聊的或者想一起学习的&#xff0c;欢迎在评论区或者私信中与我讨论&#xff01; 2025想说的话 我就把我想说的写在前面&#xff01; 不用对未来焦虑&#xff0c;不要觉得自己走…...

Python爬虫-猫眼电影的影院数据

前言 本文是该专栏的第46篇,后面会持续分享python爬虫干货知识,记得关注。 本文笔者以猫眼电影为例子,获取猫眼的影院相关数据。 废话不多说,具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。接下来,跟着笔者直接往下看正文详细内容。(附带完整代码) …...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

什么是VR全景技术

VR全景技术&#xff0c;全称为虚拟现实全景技术&#xff0c;是通过计算机图像模拟生成三维空间中的虚拟世界&#xff0c;使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验&#xff0c;结合图文、3D、音视频等多媒体元素…...