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

最大子数组和【栈和分治两种思路】

示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
其中:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
LeetCode链接:https://leetcode.cn/problems/maximum-subarray/description

方法一:
非负栈。该思路参考栈的特点,假设存在一个栈,其中记录的是最大子数组。此时,栈中的元素和存在两种情况:1、元素和非负,此时可以继续向栈中添加元素并判断是否为最大和;2、元素和为负,此时表明后续再添加元素也不会得到最大元素和,此时将栈清空即可。由于并不需要给出最大子数组,因此并不需要构建栈,只需要记录当前元素和即可。
边界情况处理。需要考虑值全小于零的情况,此处可以用注释部分的逻辑解决,也可以使用代码中的最大元素初始值设为INT_MIN,并每次都进行比较解决。
时间复杂度。单层for循环,时间复杂度为O(n)。
空间复杂度。使用了常数个额外空间,时间复杂度为O(1)。

class Solution {
public:int maxSubArray(vector<int>& nums) {int sum = 0, maxSum = INT_MIN;// vector<int> _nums=nums;// sort(_nums.begin(),_nums.end(), greater());// if(_nums[0] <= 0){//     return _nums[0];// }for (int i = 0; i < nums.size(); i++) {// 如果入栈后sum小于0,则清空栈if ((sum + nums[i]) < 0) {sum = 0;maxSum = nums[i] > maxSum ? nums[i] : maxSum;continue;}sum += nums[i];maxSum = sum > maxSum ? sum : maxSum;}return maxSum;}
};

在这里插入图片描述

方法二:
分治法(递归的一种形式)。分治的思想为将问题拆成相同情况,但是不同规模的子问题,并且可以从子问题的解得到原问题的解。对于最大数组和,可以将原始输出分为两部分,则最大数组必定出现在左部分、右部分和跨越左右两部分这三种情况之中。
边界情况处理。需要注意的边界有三点:

  1. 在计算M时,直接使用“(L + M)/2”可能会导致正溢出,因此需要使用“L + (R - L) / 2”。
  2. 递归时,边界为左闭右闭,因此递归时分别为:(L, M)、(M + 1, R)。
  3. 在计算跨越中间的最大值时,循环起始条件应该为:M、M + 1,否则会导致nums[M]被计算两次。

        时间复杂度。递归的时间复杂度为O(logn),对跨越左右的计算为O(n),因此总体复杂度为O(nlogn)。
空间复杂度。递归栈的空间复杂度一般为O(logn)。

class Solution {
public:int maxSubArray(vector<int>& nums) {return findMax(nums, 0, nums.size() - 1);}int findMax(vector<int>& nums, int L, int R) {if (L == R)return nums[L];int maxL, maxR, maxCross;// 防止大数溢出int M = L + (R - L) / 2;maxL = findMax(nums, L, M);maxR = findMax(nums, M + 1, R);maxCross = crossMax(nums, L, R, M);return max({maxL, maxR, maxCross});}int crossMax(vector<int>& nums, int L, int R, int M) {int maxL = INT_MIN;int sum = 0;for (int i = M; i >= L; i--) {sum = sum + nums[i];maxL = max({sum, maxL});}int maxR = INT_MIN;sum = 0;// 此处要从M+1开始,防止中间节点被计算两次for (int i = M + 1; i <= R; i++) {sum = sum + nums[i];maxR = max({sum, maxR});}return (maxL + maxR);}
};

在这里插入图片描述

分治法思想可以参考:https://blog.csdn.net/a1b2c3666666/article/details/138425914

http://www.dtcms.com/a/350762.html

相关文章:

  • Linux简明教程01 基础运维
  • C标准库 ---- locale.h
  • Escrcpy 3.0投屏控制软件使用教程:无线/有线连接+虚拟显示功能详解
  • 什么是生命体AI
  • TCP和UDP的使用场景
  • 【系统分析师】高分论文:论软件需求验证方法及应用
  • 用蒙特卡洛法求解三门问题和Π
  • day20 二叉树part7
  • 20.14 QLoRA微调Whisper-Large-v2终极指南:3倍速训练+显存直降68%调参秘籍
  • CVPR 2025端到端自动驾驶新进展:截断扩散模型+历史轨迹预测实现精准规划
  • 【工具安装使用-Jetson】Jetson Orin Nano 刷机和踩坑总结
  • 如何在IDEA中使用Git
  • 【嵌入式电机控制#进阶4】无感控制(二):观测器导论锁相环(全网最通俗易懂)
  • WAS/WDF资源文件工具
  • C :结构体对齐
  • vue+vite打包后的文件希望放在一个子目录下
  • Python 并发编程全面指南(多线程 多进程 进程池 线程池 协程和异步编程) 队列
  • 【leetcode】82. 删除排序链表中的重复元素(二)
  • 微算法科技(NASDAQ:MLGO)使用预测分析动态调整区块大小,构建可持续的区块链网络
  • Cursor概述及环境配置
  • 博客园-awescnb插件-geek皮肤异常问题修复
  • Java数据结构——8.优先级队列(堆)(PriorityQueue)
  • SOME/IP-SD报文中 Option Format(选项格式)-理解笔记1
  • 使用 NetworkManager 管理 Wi-Fi 热点
  • 无线USB转换器TOS-WLink网盘更新--TOS-WLink使用帮助V1.0.pdf
  • 管理驾驶舱不是面子工程!一文讲清搭建思路和具体步骤
  • 【Java SE】认识String类
  • B样条基函数:从数学原理到Python实现
  • 智数园区-前台
  • 高可用集群