LeetCode算法日记 - Day 81: 最大子数组和

目录

[1. 最大子数组和](#1. 最大子数组和)

[1.1 题目解析](#1.1 题目解析)

[1.2 解法](#1.2 解法)

[1.3 代码实现](#1.3 代码实现)


1. 最大子数组和

https://leetcode.cn/problems/maximum-subarray/description/

给你一个整数数组 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 <= 105
  • -104 <= nums[i] <= 104

1.1 题目解析

题目本质

在一维数组中找到和最大的连续子序列,本质是"连续区间求和的最优选择"问题。

常规解法

枚举所有可能的子数组(双重循环确定起点和终点),计算每个子数组的和,取最大值。

问题分析

暴力枚举需要 O(n²) 时间复杂度(或 O(n³) 如果求和也用循环),当数组长度达到 10⁵ 时会超时。关键问题是存在大量重复计算------每次都从头累加子数组的和。

思路转折

要想高效 → 必须避免重复计算 → 动态规划。核心洞察:当遍历到位置 i 时,只需要决定"是接上前面的子数组"还是"从当前位置重新开始"。这样可以在 O(n) 时间内完成,因为每个位置只需要依赖前一个位置的状态。

1.2 解法

算法思想:定义 dp[i] 表示以 nums[i] 结尾的最大子数组和。

复制代码
递推公式:dp[i] = max(dp[i-1] + nums[i], nums[i])

含义:要么延续前面的子数组(加上当前元素),要么放弃前面的(从当前元素重新开始)。

步骤拆解

**i)**初始化 DP 数组,dp[0] 设为一个极小值作为哨兵

**ii)**遍历数组,对每个位置 i 计算 dp[i] = max(dp[i-1] + nums[i-1], nums[i-1])

**iii)**遍历 DP 数组找到最大值并返回

易错点

  • **初始化问题:**dp[0] 和 cur 不能设为 0,因为数组可能全是负数。使用 Integer.MIN_VALUE/2 避免加法溢出

  • **索引偏移:**代码中 dp 数组长度为 m+1,dp[i] 对应 nums[i-1],需要注意下标映射

  • **最终结果:**不是返回 dp[m],而是返回整个 DP 数组中的最大值,因为最大子数组可能在任意位置结束

1.3 代码实现

java 复制代码
class Solution {
    public int maxSubArray(int[] nums) {
        int m = nums.length;
        int[] dp = new int[m + 1];
        dp[0] = Integer.MIN_VALUE / 2;  // 哨兵,避免溢出
        
        // 计算以每个位置结尾的最大子数组和
        for (int i = 1; i <= m; i++) {
            dp[i] = Math.max(dp[i-1] + nums[i-1], nums[i-1]);
        }
        
        // 找出所有位置中的最大值
        int cur = Integer.MIN_VALUE / 2;
        for (int i = 1; i <= m; i++) {
            cur = Math.max(cur, dp[i]);
        }
        return cur;
    }
}

复杂度分析

  • **时间复杂度:O(n),**两次遍历数组

  • **空间复杂度:O(n),**使用了 DP 数组。可优化至 O(1),因为每次只需要前一个状态

相关推荐
Pluto_CSND16 小时前
Java中的静态代理与动态代理(Proxy.newProxyInstance)
java·开发语言
百***464517 小时前
Java进阶-在Ubuntu上部署SpringBoot应用
java·spring boot·ubuntu
serve the people17 小时前
Prompts for Chat Models in LangChain
java·linux·langchain
一叶飘零_sweeeet17 小时前
不止于 API 调用:解锁 Java 工具类设计的三重境界 —— 可复用性、线程安全与性能优化
java·工具类
cynicme18 小时前
力扣3228——将 1 移动到末尾的最大操作次数
算法·leetcode
熬了夜的程序员18 小时前
【LeetCode】109. 有序链表转换二叉搜索树
数据结构·算法·leetcode·链表·职场和发展·深度优先
随意起个昵称18 小时前
【递归】二进制字符串中的第K位
c++·算法
测试老哥19 小时前
软件测试之单元测试知识总结
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例
mjhcsp19 小时前
C++ 循环结构:控制程序重复执行的核心机制
开发语言·c++·算法
立志成为大牛的小牛19 小时前
数据结构——四十一、分块查找(索引顺序查找)(王道408)
数据结构·学习·程序人生·考研·算法