求最大子数组和

65 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

1、前言

每天一个算法小练习,本篇使用Java实现。

2、题目描述

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

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104

2.1、示例1

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

2.2、示例2

输入:nums = [1]
输出:1

2.3、示例3

输入:nums = [5,4,-1,7,8]
输出:23

3、解题思路

3.1、动态规划

这道题可以使用动态规划求最大连续子串来解决,首先定义一个长度为nums.length的数组,以dp[i]记录在i位置结束的连续子串的最大和,刚开始的dp[i]要定义为nums[0],因为此时的子数组就是num[0],自身值就是最大值。那么如果dp[i-1]<=0,则dp[i]就为nums[i]。反之,dp[i] = dp[i-1] + nums[i]。

 class Solution {
    public int maxSubArray(int[] nums) {
        // nums = [-2,1,-3,4,-1,2,1,-5,4]
        // dp = [-2,1,-2,4,3,5,6,1,5]
        int length = nums.length;
        int[] dp = new int[length];
        dp[0] = nums[0];
        int max = dp[0];

        for (int i = 1; i < length; i ++) {
            // 判断是否需要更新局部最大数
            if (dp[i-1] < 0) {
                dp[i] = nums[i];
            } else {
                dp[i] = nums[i] + dp[i-1];
            }
            if (dp[i] > max) {
                // 判断是否需要更新历史最大数
                max = dp[i];
            }
        }
        return max; 
    }
}

  • 时间复杂度:O(N)O(N),N为数组的长度。因为我们只需要遍历一次数组即可。

  • 空间复杂度:O(N)O(N)

执行结果: image.png

当然,我们还可以在优化下,不去new dp 数组,进一步优化空间复杂度。

class Solution {
    public int maxSubArray(int[] nums) {
        int length = nums.length;
        int dp = nums[0]; 
        int max = nums[0];

        for (int i = 1; i < length; i ++) {
            if (dp < 0) {
                dp = nums[i];
            } else {
                dp += nums[i];
            }
            if (dp > max) {
                max = dp;
            }
        }
        return max;  
    }
}

执行结果: image.png

从提交结果来看,优化后执行结果有了很大提升。(优化后空间复杂度为O(1)O(1)

好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊