fucking-algorithm icon indicating copy to clipboard operation
fucking-algorithm copied to clipboard

动态规划设计:最大子数组 :: labuladong的算法小抄

Open utterances-bot opened this issue 3 years ago • 16 comments

文章链接点这里:动态规划设计:最大子数组

评论礼仪 见这里,违者直接拉黑。

utterances-bot avatar Dec 28 '21 16:12 utterances-bot

状态方程有个条件少了,对于 特殊case [-2,1]这种就不行; 缺少一定条件的判断 if (dp[i - 1] > 0) { dp[i] = Math.max(nums[i], nums[i] + dp[i - 1]); } else { dp[i] = nums[i]; }

edgeowner avatar Dec 28 '21 16:12 edgeowner

如果dp[i - 1] <= 0,max函数返回的也是nums[i]。不需要额外判断

super468 avatar Jan 02 '22 03:01 super468

这是不是一种贪心思想。

ElandWoo avatar Jan 13 '22 07:01 ElandWoo

用一个变量就可以表示状态转移的过程了,因为最终求解的时候,旧状态是用过即弃的,不需要保留它。

换句话说,在状态压缩的题解代码里:

dp_1 = Math.max(nums[i], nums[i] + dp_0);
dp_0 = dp_1;

dp_1 其实没有什么存在的必要,因此上面的两句可以合并成一句:

dp = Math.max(nums[i], nums[i] + dp);

DiamondI avatar Jan 23 '22 04:01 DiamondI

这个应该就是Kadane's algorithm

ginward avatar Mar 03 '22 03:03 ginward

其实本题可以利用滑动窗口去解决,每次记录了当前的最大值即可 缩小窗口的时机在sum<0时,因为此时该窗口肯定不会是所要求的。

class Solution
{
	public int maxSubArray(int[] nums) {
		int left=0;
		int right=0;
		int sum=0;
		int maxsum=nums[0];
		while(right<nums.length())
		{
			sum+=nums[right];
			if(sum<0)
			{
				sum-=nums[left];
				left++;
			}
			//进行答案的更新
			maxsum=Math.max(maxsum,sum);
		}
		//进行特殊情况的处理
		        int maxVal = nums[0];
        for (int i = 1; i <nums.size(); i++) {
            maxVal = max(maxVal, nums[i]); 
        }
        return maxVal < 0 ? maxVal : maxsum;
	}
}

cillian-bao avatar May 16 '22 05:05 cillian-bao

打卡,感谢!

bert82503 avatar May 24 '22 14:05 bert82503

以nums[i]结尾的最大子数组和情况之二和前面连成一个数组,但如何保证和前面的一定是连续的呢

enthural avatar Jun 08 '22 03:06 enthural

本题的滑动窗口解法,重点在于maxSum的初始化

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        // 滑动窗口(快慢指针

        int left = 0, right = 0;
        int sum = 0, maxSum = INT32_MIN; // 重点:preMaxSum一定要设置为最小负数,这样遇到全负数组的时候才能不出错
        while(right < nums.size()){
            // 移入
            int c = nums[right];
            // 增大窗口
            right++;
            // 更新窗口
            sum += c;
            maxSum = sum > maxSum ? sum : maxSum;

            // 判断左侧窗口是否要收缩
            while(sum < 0){
                // 移除
                int d = nums[left];
                // 缩小窗口
                left++;
                // 更新窗口
                sum -= d;
            }
        }
        return maxSum;
    }
};

Maxiah avatar Jun 29 '22 02:06 Maxiah

// 要么自成一派,要么和前面的子数组合并 dp[i] = Math.max(nums[i], nums[i] + dp[i - 1]); 我在想,如果数组是[4,5,-1,-1],那岂不是最后dp[i]是7了?求解,我不知道是哪里看错了

mianbao374 avatar Jul 05 '22 12:07 mianbao374

@mianbao374 没错,dp的定义就是以num[i]为结尾的[最大子数组和],dp[n-1]确实是7,但是问题求的最终结果是dp数组的最大值max(dp[i])=dp[1]=9,你应该是看漏了

zclorne avatar Jul 09 '22 12:07 zclorne

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int subSum=0;
        int result=INT_MIN;
        for(int i=0;i<nums.size();i++){
            subSum=max(subSum+nums[i],nums[i]);
            result=max(result,subSum);
        }
        return result;
    }
};

buhubaiyu avatar Jul 13 '22 09:07 buhubaiyu

@mianbao374 没错,dp的定义就是以num[i]为结尾的[最大子数组和],dp[n-1]确实是7,但是问题求的最终结果是dp数组的最大值max(dp[i])=dp[1]=9,你应该是看漏了

明白了,是我看漏了

mianbao374 avatar Jul 13 '22 09:07 mianbao374

确实,看了下评论区读者的讨论,本题可以用滑动窗口算法,我这两天把滑动窗口算法的思路补充到文章中

labuladong avatar Jul 14 '22 02:07 labuladong

有谁能给个 dp 函数的解法

oliyg avatar Jul 19 '22 10:07 oliyg

摩尔投票

    public int maxSubArray(int[] nums) {
        int n = nums.length;
        int sum = 0;
        int res = Integer.MIN_VALUE;
        for(int num : nums){
            if(sum < 0){
                sum = num;
            }else{
                sum += num;
            }
            res = Math.max(res, sum);
        }
        return res;
    }

deepbreath373 avatar Jul 23 '22 03:07 deepbreath373

Prefix sum相减:

class Solution {
    public int maxSubArray(int[] nums) {
        int minSum = Integer.MAX_VALUE;
        int sum = 0;
        int result = Integer.MIN_VALUE;
        for (int num: nums){
            minSum = Math.min(sum, minSum);
            sum+=num;
            result = Math.max(sum-minSum, result);
        }
        return result;
    }
}

SerenaZZZZZ avatar Sep 06 '22 00:09 SerenaZZZZZ