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

LeetCode 53. 最大子数组和(四种解题思路)包含扩展返回最大和的数组

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

示例 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

思路

暴力解法:

两层for循环,第一层for循环设置起始位置,第二层for循环遍历数组,时间复杂度On方

class Solution {public int maxSubArray(int[] nums) {int res = Integer.MIN_VALUE;for (int i = 0; i < nums.length; i++) {int count = 0;for (int j = i; j < nums.length; j++) {count += nums[j];res = Math.max(res, count);}}return res;}
}
贪心解法:

如果 -2 1 在一起,计算起点的时候,一定是从 1 开始计算,因为负数只会拉低总和,这就是贪心贪的地方!

局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素的话“连续和”只会越来越小。

全局最优:选取最大“连续和”

从代码角度上来讲:遍历 nums,从头开始用 count 累积,用result记录最大和的终止位置,如果 count 一旦加上 nums[i]变为负数,那么就应该从 nums[i+1]开始从 0 累积 count 了,因为已经变为负数的 count,只会拖累总和。

class Solution {public int maxSubArray(int[] nums) {int res = Integer.MIN_VALUE;int count = 0;for (int i = 0; i < nums.length; i++) {count += nums[i];res = Math.max(res, count);if (count < 0) count = 0;}return res;}
}
前缀和

因为子数组的和就是前缀和-最小前缀和的差,所以我们可以在一层for循环中,先计算前缀和-最小前缀和,再更新最小前缀和

class Solution {public int maxSubArray(int[] nums) {int res = Integer.MIN_VALUE;int sum = 0;int preSum = 0;for (int i = 0; i < nums.length; i++) {sum += nums[i]; //记录前缀和res = Math.max(res, sum - preSum); //记录结果preSum = Math.min(preSum, sum); // 更新最小前缀和}return res;}
}
动态规划
  1. 确定dp数组以及下标含义:dp[i]:表示以 nums[i] 结尾 的 连续 子数组的最大和。
  2. 递推公式:dp[i]只有两个方向可以推出来:
    • dp[i - 1] + nums[i],即:nums[i]加入子数组和
    • nums[i],即:从头开始计算子数组和
  1. 初始化:dp[0] = nums[0]
  2. 遍历顺序:从左往右for循环遍历
class Solution {public int maxSubArray(int[] nums) {// dp[i]:以下标i结尾的最大子数组和int[] dp = new int[nums.length];dp[0] = nums[0];int res = dp[0];for (int i = 1; i < nums.length; i++) {if (dp[i - 1] > 0) {dp[i] = dp[i - 1] + nums[i];} else {dp[i] = nums[i];}res = Math.max(res, dp[i]);}return res;}
}

如果是返回最大和的最数组呢?

应用动态规划的解题思路

class Solution {public int maxSubArray(int[] nums) {// dp[i]:以下标i结尾的最大子数组和int[] dp = new int[nums.length];dp[0] = nums[0];int res = dp[0];int maxStart = 0, maxLen = 1; //记录最大子数组起点和长度int start = 0, len = 1; //记录子数组的起点和长度for (int i = 1; i < nums.length; i++) {if (dp[i - 1] > 0) {dp[i] = dp[i - 1] + nums[i];len++;} else {dp[i] = nums[i];start = i;len = 1;}if (dp[i] > res) {res = dp[i];maxStart = start;maxLen = len;}}System.out.println(maxLen);System.out.println(Arrays.toString(Arrays.copyOfRange(nums, maxStart, maxStart + maxLen)));return res;}
}
http://www.dtcms.com/a/394148.html

相关文章:

  • RTX 4090助力深度学习:从PyTorch到生产环境的完整实践指南——高效模型训练与优化策略
  • 23种设计模式之【桥接模式】-核心原理与 Java实践
  • LabVIEW手部运动机能实验
  • 669. 修剪二叉搜索树
  • 大QMT自动可转债申购
  • PolarCTF PWN 网络安全2023秋季个人挑战赛刷题
  • MySQL-day4_02(事务)
  • JUC(8)线程安全集合类
  • springboot中@EnableAsync有什么作用
  • Spark专题-第二部分:Spark SQL 入门(6)-算子介绍-Generate
  • C#练习题——Dictionary
  • Feign
  • SPA小说集之三《森林城市反甩锅战:ERP的权责边界》
  • Qt(模态对话框和非模态对话框)
  • 【无标题】物联网 frid卡控制
  • 【LLM LangChain】 模型绑定工具+调用工具(手动调用/LangGraph/AgentExecutor)+相关注意事项
  • 图神经网络(GNN)入门:用PyG库处理分子结构与社会网络
  • 【C++】编码表 STL简介:STL是什么,版本,六大组件,重要性以及学习方法总结
  • show_interrupts函数的进一步解析及irq_desc结构体
  • Kafka面试精讲 Day 19:JVM调优与内存管理
  • 10.vector容器
  • Linux系统介绍
  • MFC中的CMFCDynamicLayout类的介绍
  • UniScene 统一驾驶场景 | 生成语义占据 | 生成多视角视频 | 生成激光点云 CVPR2025
  • Git 简明教程:从原理到实战
  • 【设计模式】中介者模式
  • nginx添加modsecurity插件
  • 代码上传Github:SSH法
  • 【iOS】AFNetworking初步了解及使用
  • JVM实战-G1参数调优