子数组最大累加和问题

一、例题一

1)题目描述

2)题目分析:

首先定义dp数组:dp[i] 表示以i位置的数做结尾,并能向左延申的最大累加和。并且每一个i位置的dp值都表示从0~i的最优情况,即每一次更新dp[i]时只需和dp[i - 1]进行比较,如果dp[i - 1]<= 0说明再往左也“无利可图”,所以我们更新

                                           dp[i] = Math.max(nums[i] , dp[I - 1] + nums[i])

扩展:求最长区间的left、right

我们需要一个l、r和pre来记录每一次更新的答案,然后left、right、sum为最终答案。

当 pre >= 0   pre += nums[r];

    pre < 0 pre = nums[r] ; l = r;

样例 【5 , -2 , 3 , -9 , 4 , -1 ,3 , 1 , -9 , 4】

3)代码

package class70;

public class 最大子数组和 {

        public int maxSubArray1(int[] nums) {

        int n = nums.length;

        //dp[i] : 子数组必须以i位置的数做结尾,往左延申出来的最大累计和

        int dp[] = new int[n];

        dp[0] = nums[0]; //第一个就是nums[0]本身

        int ans = dp[0]; //第一个答案需要更新为数组的第一个

        for(int i = 1 ; i < n ; i ++) {

                dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]); //两种情况,因为dp[i - 1]表示i - 1位置前的最大累加和,但是有可能dp[i - 1]会是一个负数,所以需要取两种情况的最大值

                ans = Math.max(ans, dp[i]); //更新ans

        }

        return ans;

    }

        

        //空间压缩

        public int maxSubArray2(int[] nums) {

                int n = nums.length;

                int ans = nums[0];

                int pre = nums[0]; //代替dp的更新

                for(int i = 1 ; i < n ; i ++) {

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

                        ans = Math.max(ans , pre);

                }

                return ans;

        }

        

        //要求返回leftrightsum

        public static int left;

        public static int right;

        public static int sum;

        public static void extra(int nums[]) {

                sum = Integer.MIN_VALUE;

                int pre = Integer.MIN_VALUE;

                for(int l = 0 , r = 0 ; r < nums.length ; r ++) {

                        if(pre >= 0) {

                                pre += nums[r];

                        }else {

                                pre = nums[r];

                                l = r;

                        }

                        if(pre > sum) {

                                left = l;

                                right = r;

                                

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值