uacs2024

导航

leetcode 1749. 任意子数组和的绝对值的最大值

1749. 任意子数组和的绝对值的最大值

没做出来🤡

法一:动态规划

class Solution {
public:
    int maxAbsoluteSum(vector<int>& nums) {
        int res = 0;
        // 初始化以当前元素为结尾的子数组的最大和f_max为0
        int f_max = 0;
        // 初始化以当前元素为结尾的子数组的最小和f_min为0
        // 注意:这里用最小和而不是负的最大和,是为了同时处理正负数情况,简化逻辑
        int f_min = 0;
        
        for(int &n : nums){
            // 更新f_max:如果前面的子数组和大于等于0,则加上当前元素n可能使和更大;
            // 否则,从当前元素n开始重新计算子数组和(即f_max = n),因为加上前面的负数只会使和变小
            f_max = max(f_max, 0) + n;
            
            // 更新f_min:逻辑与f_max类似,但用于找最小和。
            // 如果前面的子数组和小于等于0,则加上当前元素n可能使和更小;
            // 否则,从当前元素n的相反数开始重新计算子数组和(即f_min = -n的相反数,但这里直接写为n加上之前的最小负和),
            // 因为加上前面的正数只会使和变大,而我们需要找最小和,所以这里通过记录最小负和来间接找到最小和
            f_min = min(f_min, 0) + n;
            
            // 更新结果res:比较当前的最大绝对和(即f_max的绝对值与-f_min的绝对值中较大的一个)与之前的最大绝对和res
            // -f_min是因为f_min记录的是最小和,而我们需要的是最大绝对和,所以取反来比较
            res = max(res, max(f_max, -f_min));
        }

        // 返回遍历结束后找到的最大绝对和
        return res;
    }
};

法二:前缀和

class Solution {
public:
//由于子数组和等于两个前缀和的差,那么取前缀和中的最大值与最小值,它俩的差就是答案。
//如果最大值在最小值右边,那么算的是最大子数组和。如果最大值在最小值左边,那么算的是最小子数组和的绝对值(相反数).
    int maxAbsoluteSum(vector<int>& nums) {
        int sum = 0;// 初始化当前的前缀和为0
        int minSum = 0;// 初始化最小前缀和为0,用于记录遍历过程中遇到的最小前缀和
        int maxSum = 0;// 初始化最大前缀和为0,用于记录遍历过程中遇到的最大前缀和
        
        for(int &n : nums){           
            sum += n; //更新当前的前缀和,即当前元素n加上之前的前缀和
            minSum = min(minSum, sum);// 更新最小前缀和,如果当前前缀和小于已知的最小前缀和,则更新
            maxSum = max(maxSum, sum);// 更新最大前缀和,如果当前前缀和大于已知的最大前缀和,则更新
        }
        
        // 返回最大前缀和与最小前缀和的差,这个差值即为子数组和的最大绝对值
        // 因为无论最大前缀和在前还是在后,与最小前缀和的差值都能反映出子数组和的最大绝对值
        // 如果最大前缀和在最小前缀和的右边,那么差值为正,表示最大子数组和;
        // 如果最大前缀和在最小前缀和的左边,那么差值为负,但由于我们要求的是绝对值,所以结果仍然正确。
        return maxSum - minSum;
    }
};

 

posted on 2024-12-30 18:21  ᶜʸᵃⁿ  阅读(24)  评论(0)    收藏  举报