zoukankan      html  css  js  c++  java
  • 最大子序和 动态规划|线段树实现

    最大子序和 动态规划|线段树实现


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

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

    进阶:
    如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
    链接:https://leetcode-cn.com/problems/maximum-subarray/

    动态规划法

    公式 dp[i] = max(nums[i], dp[i - 1] + nums[i]),遍历数组,如果前面的结果dp[i-1]为负值就将其丢弃,设置res记录最大值,为了减少空间复杂度,直接改为dp即可

    var maxSubArray = function (nums) {
        let res = Number.MIN_SAFE_INTEGER, dp = 0;
        for (let i = 0; i < nums.length; i++) {
            //dp小于0直接抛弃
            dp = Math.max(nums[i], dp + nums[i]);
            //记录最大值
            res = Math.max(res, dp);
        }
        return res;
    };
    

    分治法-类似线段树解决方案

    /* 线段树结点 [x,y] */
    function TreeNode(x, y, xSum, maxSum, ySum, sum) {
        this.xSum = xSum;//以x开头的最大连续序列和
        this.maxSum = maxSum;//区间[x,y]最大序列和
        this.ySum = ySum;//以y结尾的最大连续序列和
        this.sum = sum;//区间和
    }
    /* 将xNode,yNode与父节点node关联 */
    function pushUp(x, y, xNode, yNode) {
        /* x开头的最大连续序列和 */
        let xSum = Math.max(xNode.xSum, xNode.sum + yNode.xSum);
        /* y结尾的做大连续序列和 */
        let ySum = Math.max(yNode.ySum, yNode.sum + xNode.ySum);
        /* 区间[x,y]最大序列和 */
        let maxSum = Math.max(Math.max(xNode.maxSum, yNode.maxSum), xNode.ySum + yNode.xSum);
        /* 区间和 */
        let sum = xNode.sum + yNode.sum;
        /* 返回结点 */
        return new TreeNode(xSum, maxSum, ySum, sum);
    }
    function maxSubArray(nums) {
        function build(x, y) {
            if (x === y) {
                /* 返回叶子节点 */
                return new TreeNode(nums[x], nums[x], nums[x], nums[x]);
            }
            let m = Math.floor(x + y >> 1);
            let xNode = build(x, m);
            let yNode = build(m + 1, y);
            return pushUp(xNode, yNode);
        }
        return build(0, nums.length - 1).maxSum;
    }
    
    1. 创建TreeNode类记录结点数据
    /* 线段树结点 [x,y] */
    function TreeNode(x, y, xSum, maxSum, ySum, sum) {
        this.xSum = xSum;//以x开头的最大连续序列和
        this.maxSum = maxSum;//区间[x,y]最大序列和
        this.ySum = ySum;//以y结尾的最大连续序列和
        this.sum = sum;//区间和
    }
    
    1. 建立父区间与左右子区间的联系
    • [x, y]区间xSum等于[x, m]xSum,要么等于[x, m]sum 加上[m + 1, y]xSum取大。
    • [x, y]区间ySum等于[m + 1, y]ySum,要么等于[m + 1, y]sum 加上[x, m]ySum取大。
    • [x, y]区间maxSum等于可能是[x, m]maxSum[m + 1, y]maxSum中取大, 可能是[x, m]ySum[m + 1, y]xSum 求和,三者取大。
    /* 将xNode,yNode与父节点node关联 */
    function pushUp(x, y, xNode, yNode) {
        /* x开头的最大连续序列和 */
        let xSum = Math.max(xNode.xSum, xNode.sum + yNode.xSum);
        /* y结尾的做大连续序列和 */
        let ySum = Math.max(yNode.ySum, yNode.sum + xNode.ySum);
        /* 区间[x,y]最大序列和 */
        let maxSum = Math.max(Math.max(xNode.maxSum, yNode.maxSum), xNode.ySum + yNode.xSum);
        /* 区间和 */
        let sum = xNode.sum + yNode.sum;
        /* 返回结点 */
        return new TreeNode(xSum, maxSum, ySum, sum);
    }
    
  • 相关阅读:
    HTTP断点续传 规格严格
    Java Shutdown 规格严格
    linux 命令源码 规格严格
    JTable调整列宽 规格严格
    linux 多CPU 规格严格
    Hello can not find git path 规格严格
    Kill 规格严格
    拜拜牛人 规格严格
    Swing 规格严格
    Debugging hangs in JVM (on AIX but methodology applicable to other platforms) 规格严格
  • 原文地址:https://www.cnblogs.com/aeipyuan/p/12990187.html
Copyright © 2011-2022 走看看