LeetCode 53 – 最大子数组和

题目描述

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

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

示例 1:

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

题目分析

动态规划

动态规划,设 dp[i] 表示以 i 为结尾的子数组的最大和
则有 dp[i] = Math.max(dp[i – 1] + nums[i], nums[i])
进一步会发现 dp 数组的每个元素都只使用一次,因此可以简化为单个变量
时间复杂度 O(n),空间复杂度 O(1)

递归分治

把数组从中间一分为二:左区间 left、右区间 right
设 maxSum 为子区间最大和,maxLSum 为左边界最大区间和,maxRSum 为右边界最大区间和,sum 为区间和。
则有
– maxSum = max{left.maxSum,right.maxSum,left.maxRSum + right.maxLSum}
– maxRSum = max{right.maxRSum, left.maxRSum + right.sum}
– maxLSum = max{left.maxLSum, left.sum + right.maxLSum}

因此可以直接递归来解决,递归的出口就是区间内只剩一个数字。
时间复杂度 O(n)

Java

public int maxSubArray1(int[] nums) {
    int dp = nums[0];
    int ans = nums[0];
    for (int i = 1; i < nums.length; i++) {
        dp = Math.max(dp + nums[i], nums[i]);
        ans = Math.max(dp, ans);
    }
    return ans;
}


private class Node {
    int start, end;
    int sum; // 区间和
    int maxSum, maxLSum, maxRSum;// 子区间最大和、左边界最大区间和、右边界最大区间和

    public Node(int start, int end) {
        // 前闭后闭
        this.start = start;
        this.end = end;
    }

    public void calculate(int[] nums) {
        if (start == end) {
            sum = nums[start];
            maxSum = nums[start];
            maxLSum = nums[start];
            maxRSum = nums[start];
            return;
        }

        int mid = (start + end) / 2;
        Node left = new Node(start, mid);
        Node right = new Node(mid + 1, end);
        left.calculate(nums);
        right.calculate(nums);

        sum = left.sum + right.sum;

        maxSum = Math.max(left.maxSum, right.maxSum);
        maxSum = Math.max(maxSum, left.maxRSum + right.maxLSum);

        maxLSum = Math.max(left.maxLSum, left.sum + right.maxLSum);
        maxRSum = Math.max(right.maxRSum, right.sum + left.maxRSum);
    }
}

public int maxSubArray2(int[] nums) {
    Node node = new Node(0, nums.length - 1);
    node.calculate(nums);
    return node.maxSum;
}

Kotlin

fun maxSubArray(nums: IntArray): Int {
    var dp = nums[0]
    var ans = nums[0]
    for (i in 1 until nums.size) {
        dp = max(nums[i], dp + nums[i])
        ans = max(ans, dp)
    }
    return ans
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部