Leetcode 1749 Maximum Absolute Sum of Any Subarray

题目理解:求任意子数组的最大和或者最小和。看了一眼数据规模,$1 \leq nums.length \leq 10^5 $。这个数组太长了,让我失去试试暴力解法($\mathcal{O}(n^2)$)的兴趣。这道题考的内容看起来像是双指针或者前缀和,当然也可能是其他解法,但是我暂时没有时间思考其他解法。

使用前缀和: 子数组的最大和或者最小和,只可能是当前的和,减去以前最小的前缀和或者以前最大的前缀和,包含了所有正负的可能。

static int x = [] () {ios::sync_with_stdio(false); cin.tie(0); return 0;} ();
class Solution {
 public:
  int maxAbsoluteSum(vector<int>& nums) {
    vector<int> sums(nums.size());
    partial_sum(nums.begin(), nums.end(), sums.begin());
    int premin = 0, premax = 0;
    int res = 0;  // empty subarray has sum equals to 0
    for (int i = 0, n = nums.size(); i < n; ++i) {
      res = max({res, abs(sums[i] - premin), abs(sums[i] - premax)});
      premax = max(premax, sums[i]);
      premin = min(premin, sums[i]);
    }
    return res;
  }
};

写完后发现,没有必要先计算出前缀和,只需要计算出当前的所有数的和,记住最大前缀和以及最小前缀和,就可以得出答案。上述代码可以简化,两遍遍历可以变为一遍,虽然没有减少计算量,但是代码会简洁一些。

static int x = [] () {ios::sync_with_stdio(false); cin.tie(0); return 0;} ();
class Solution {
 public:
  int maxAbsoluteSum(vector<int>& nums) {
    int premin = 0, premax = 0, res = 0, sum = 0;
    for (const int a: nums) {
      sum += a;
      res = max({res, abs(sum - premin), abs(sum - premax)});
      premax = max(premax, sum);
      premin = min(premin, sum);
    }
    return res;
  }
};

#直达链接

LeetCode 1749. Maximum Absolute Sum of Any Subarray