leetcode - [53]最大子序和|刷题打卡

175 阅读1分钟

1. 题目描述

[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 = [0]
输出:0
    
示例 4:
输入:nums = [-1]
输出:-1
    
示例 5:
输入:nums = [-100000]
输出:-100000
    
    
提示:
1 <= nums.length <= 3 * 104
-105 <= nums[i] <= 105
进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。
Related Topics 数组 分治算法 动态规划

2. 思路分析

method1

​ 暴力解决,没啥好说

method2

​ 我想太多了,被题目的数组顺序子序和扣住了,想着找到下标位的大小来定义动态规划的dp数组。大家看着当做反面教材即可

method3

​ 应该是最佳解了。 时间复杂度= O(n) 空间复杂度 O(1),没有dp表,但是用了精髓

​ 要知道整个数组的最大和。至少都需要一个循环,我们的判断条件可以理解为 如果数组之前的最大值加上当前值,还没有大过当前值,则还不如从当前值开始计算和。

method4

​ 理解同 method3 ,但是,定义了一个dp数组,会占用一定的空间

时间复杂度= O(n) 空间复杂度 O(n)

3. AC代码

public class No53 {
    public int maxSubArray(int[] nums) {
//        return method1(nums);
//        return method2(nums);
        return method3(nums);
//        return method4(nums);
    }

    /**
     * 直接暴力
     *
     * 执行耗时:133 ms,击败了5.24% 的Java用户
     * 内存消耗:38.3 MB,击败了78.36% 的Java用户
     * @param nums
     * @return
     */
    private int method1(int[] nums) {
        int maxSum = Integer.MIN_VALUE;

        for (int i = 0; i < nums.length; i++) {
            int tempSum = 0;
            for (int j = i; j < nums.length; j++) {
                tempSum += nums[j];
                if (tempSum > maxSum) {
                    maxSum = tempSum;
                }
            }
        }

        return maxSum;
    }

    /**
     * 错误示范!!!!!
     * 我想太多了
     *
     * Memory Limit Exceeded
     * @param nums
     * @return
     */
    private int method2(int[] nums) {
        int maxSum = Integer.MIN_VALUE;
        if(nums.length == 1) {
            return nums[0];
        }

        int[][] dp = new int[nums.length+1][nums.length+1];
        dp[0][0] = 0;
        for (int i = 1; i < nums.length+1; i++) {
            dp[i][i] = nums[i-1];
            for (int j = i; j < nums.length+1; j++) {
                dp[i][j] = dp[i][j-1] + nums[j-1];
                int tempSum = dp[i][j];
                if (tempSum > maxSum) {
                    maxSum = tempSum;
                }
            }
        }
        return maxSum;
    }

    /**
     * 理解题目,理解题目
     *
     * 执行耗时:1 ms,击败了94.76% 的Java用户
     * 内存消耗:38.4 MB,击败了60.37% 的Java用户
     * @param nums
     * @return
     */
    private int method3(int[] nums) {
        int maxSum = nums[0];
        int temp = 0;

        for (int num : nums) {
            // 如果到当前位置的数组之和小于当前这个数,直接从这个数开始重算
            temp = Math.max(temp+num,num);
            maxSum = Math.max(temp,maxSum);
        }
        return maxSum;
    }

4. 总结

​ 品题目,品题目

​ 根据实际情况出发,没必要为了套公式而套公式。

参考内容

​ leetCode题解 - 53.最大子序和,动态规划解法

​ leetCode题解 - |最大子序和(动态规划)


​ 本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情