算法力扣刷题记录 八十七【53. 最大子序和】

embedded/2024/10/21 3:51:43/

前言

贪心章节第4篇。动态规划章节第10篇。同一题,两种方法。
记录 八十七【53. 最大子序和】


一、题目阅读

给你一个整数数组 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

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


二、尝试实现

2.1 分析题目,确定方法

  1. 题目含义有以下几点:
  • 子数组是原来数组中的一个连续部分,说明数组nums保持原有顺序,不能排序,导致顺序改变;
  • 只说找到连续子数组的最大值,这个连续子数组中元素个数是多少不确定;
  • 从哪个元素开始构建连续子数组也不知道。
  1. 不过想求最大和,那么这个连续子数组中应该正数之和尽可能大,负数之和尽可能大。用滑动窗口能否解决?……(滑动窗口,没想好移动规则)
  2. 暴力求解。时间复杂度肯定高,根据提示的nums.length预判一定超时。不过按照暴力遍历写出一份代码。如下:
    分析时间复杂度:循环次数有n*(n+1)/2,所以是O(n 2)。提交后:超时。
    class Solution {
    public:int maxSubArray(vector<int>& nums) {int result = INT_MIN;for(int i = 0;i < nums.size();i++){int sum = 0;for(int j = i;j < nums.size();j++){sum += nums[j];result = max(result,sum);}}return result;}
    };
    
  3. 滑动窗口应该是正确的思路。但是没想出移动规则。

三、参考学习

【53. 最大子序和】 贪心思路参考学习链接

3.1贪心思路

  1. 连续和+nums[i]:如果连续和是负数,那么nums[i]会变小,再往后加值,已经拖累了总和。所以:当连续和=负数,从nums[i]作为新起点,重新开始
  2. 如果连续和是正数,后面的值+连续和,对后面的值起增大作用。
  3. 模拟过程:箭头代表,由于连续和为正,扩展区间。同时用result记录过程中的最大值。没有箭头,更换颜色,代表连续和为负,更新起点。
    在这里插入图片描述

3.2 代码实现【贪心】

在暴力解法的基础上改:

class Solution {
public:int maxSubArray(vector<int>& nums) {int result = INT_MIN;int sum = 0;for(int i = 0;i < nums.size();i++){if(sum < 0){sum = 0;}sum += nums[i];result = max(result,sum);}return result;}
};

3.3 动态规划思路【分治法】

3.3.1 沿用贪心的思路——推动态规划实现

  1. 指明动态规划也可求解。那么就需要去找状态转移过程。
  2. 定义dp数组和下标的含义:
  • dp数组大小和nums数组大小相等;
  • dp[i]:当以nums[i]作为子序列的最后一个元素(包含nums[i]),最大的连续子序列和为dp[i]。
  1. 状态转移过程:(思路还是用贪心的思路)
  • 如果dp[i-1] < 0,那么重新开始。dp[i] = nums[i]。
  • 如果dp[i-1] > 0,那么dp[i] = dp[i-1]+nums[i];
  • 同时用一个result记录过程中的dp数组中的最大值。
  1. dp初始化:dp[0] = nums[0];
  2. 遍历顺序:从递推公式看,从前往后。
  3. 总结:贪心中用int sum来保存连续和。此处用dp数组来保存连续和

3.3.2代码实现【动态规划】

class Solution {
public:int maxSubArray(vector<int>& nums) {vector<int> dp(nums.size(),0);//初始化dp[0] = nums[0];int result = nums[0];for(int i =1;i < nums.size();i++){if(dp[i-1] < 0) dp[i] = nums[i];//重新开始else {dp[i] = dp[i-1]+nums[i];}result = dp[i] > result ? dp[i]:result;}return result;}
};

3.3.3动态规划参考思路

【53. 最大子序和】 动态规划参考详解

  1. dp数组含义一致:dp[i]:当以nums[i]作为子序列的最后一个元素(包含nums[i]),最大的连续子序列和为dp[i]。
  2. 递推公式:只有两种情况
  • 第一种:把nums[i]囊括到之前的子序列中,dp[i-1] + nums[i];
  • 第二种:从nums[i] 重新开始子序列。nums[i]。
  • 所以取最大值:max(nums[i] , dp[i-1] + nums[i])
  1. 初始化:dp[0] = nums[0].
  2. 遍历顺序:从前往后,根据递推公式。
  3. return dp数组中的最大值。
  4. 代码实现和**3.3.2代码实现【动态规划】**一致。

总结

在这里插入图片描述
(欢迎指正,转载标明出处)


http://www.ppmy.cn/embedded/97464.html

相关文章

JavaEE 第9节 阻塞队列详解

一、概念 阻塞队列是在普通队列&#xff08;先进先出的数据结构&#xff09;的基础上增加了阻塞属性的特殊队列 1&#xff09;当阻塞队列空的时候&#xff0c;如果继续出队元素会进入阻塞状态&#xff0c;直到其他线程入队元素。 2&#xff09;当阻塞队列满的时候&#xff0c;…

[000-01-030].Zookeeper学习大纲

我的博客大纲 我的后端学习大纲 第一步&#xff1a;Zookeeper是什么 1.第01节&#xff1a;Zookeeper概述 第二步&#xff1a;Zookeeper怎么使用&#xff1a; 2.1.开发环境搭建 2.第02节 &#xff1a;Zookeeper本地安装3.第03节 &#xff1a;Zookeeper集群操作 2.2.具体使用…

企业级批量无人值守安装

企业级批量无人值守安装 一、批量无人值守安装1.简介PXE工作流程 2.核心技术&#xff08;dhcp、httpd、tftp&#xff09;3.实验3.1 准备环境3.2 防护关闭3.3 软件安装3.4 软件配置DHCP服务设置httpd服务配置tftp服务配置 3.5 编写引导安装相关文件&#xff0c;放到指定位置3.5.…

【漫谈C语言和嵌入式013】函数指针与指针函数详解:概念、区别及实例

在C语言中&#xff0c;理解指针的各种用法是非常关键的&#xff0c;特别是当涉及到更复杂的概念如函数指针和指针函数时。这两者听起来非常相似&#xff0c;但实际上是完全不同的概念。在这篇博客中&#xff0c;我们将探讨函数指针和指针函数的定义、区别以及如何在实际中使用它…

共享经济背景下校园、办公闲置物品交易平台-计算机毕设Java|springboot实战项目

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

yolov8语义分割训练-验证-推理-转化-数据集(代码+教程)

实例分割概述 实例分割是计算机视觉任务的一种&#xff0c;它超越了简单的物体检测&#xff0c;能够识别图像中的单个物体并将其从图像的其余部分分割出来。这种高级别的分割技术不仅能定位物体的位置&#xff0c;还能精确描绘出每个物体的实际形状。 实例分割模型的输出 实…

十五年以来 — 战略性云平台服务的演进路径之全面呈现(含亚马逊、微软和谷歌)

Gartner每年都发布对全球IaaS平台进行评估的魔力象限报告。2023年底&#xff0c;Gartner将此项评估的名称改为“战略性云平台服务”&#xff08;Strategic cloud platform services&#xff09;&#xff0c;尽管其核心仍为IaaS&#xff0c;但是&#xff0c;毫无疑问&#xff0c…

redis字符串若干记录

1、字符串 redis字符串支持二进制安全、redis中的健都为字符串类型、redis中所有的健和值都为redisObject变量 SDS len:已用字节长度 alloc&#xff1a;已申请字节长度 flag&#xff1a;低三位代表sdshdr类型 buf&#xff1a;字符串内容- 根据len判断SDS的类型 &#xff08;…