Trionic Array II

hard array dynamic programming subarray

Problem

A trionic subarray nums[l..r] (with 0 ≤ l < r < n) has split points l < p < q < r where nums[l..p] is strictly increasing, nums[p..q] is strictly decreasing, and nums[q..r] is strictly increasing — an up-down-up shape. Return the maximum sum of any trionic subarray. At least one is guaranteed to exist.

Inputnums = [0, -2, -1, -3, 0, 2, -1]
Output-4
Take l=1, p=2, q=3, r=5: [-2,-1] up, [-1,-3] down, [-3,0,2] up. Sum = (-2)+(-1)+(-3)+0+2 = -4.

def maxSumTrionic(nums):
    NEG = float("-inf")
    # dpk[i] = best sum of a run ending at i after finishing phase k
    # phase1 = increasing, phase2 = decreasing, phase3 = increasing
    dp0, dp1, dp2, dp3 = nums[0], NEG, NEG, NEG
    best = NEG
    for i in range(1, len(nums)):
        n0, n1, n2, n3 = nums[i], NEG, NEG, NEG   # dp0 always restarts at i
        if nums[i] > nums[i - 1]:                  # an increasing step
            n1 = max(dp0, dp1) + nums[i]           # open or extend phase1
            n3 = max(dp2, dp3) + nums[i]           # open or extend phase3
        elif nums[i] < nums[i - 1]:                # a decreasing step
            n2 = max(dp1, dp2) + nums[i]           # open or extend phase2
        dp0, dp1, dp2, dp3 = n0, n1, n2, n3
        best = max(best, dp3)                      # dp3 = a full trionic run
    return best
function maxSumTrionic(nums) {
  const NEG = -Infinity;
  // dpk = best sum of a run ending at i after finishing phase k
  // phase1 = increasing, phase2 = decreasing, phase3 = increasing
  let dp0 = nums[0], dp1 = NEG, dp2 = NEG, dp3 = NEG;
  let best = NEG;
  for (let i = 1; i < nums.length; i++) {
    let n0 = nums[i], n1 = NEG, n2 = NEG, n3 = NEG; // dp0 restarts at i
    if (nums[i] > nums[i - 1]) {                    // an increasing step
      n1 = Math.max(dp0, dp1) + nums[i];            // open or extend phase1
      n3 = Math.max(dp2, dp3) + nums[i];            // open or extend phase3
    } else if (nums[i] < nums[i - 1]) {             // a decreasing step
      n2 = Math.max(dp1, dp2) + nums[i];            // open or extend phase2
    }
    dp0 = n0; dp1 = n1; dp2 = n2; dp3 = n3;
    best = Math.max(best, dp3);                     // dp3 = a full trionic run
  }
  return best;
}
long maxSumTrionic(int[] nums) {
    final long NEG = Long.MIN_VALUE / 4;
    // dpk = best sum of a run ending at i after finishing phase k
    // phase1 = increasing, phase2 = decreasing, phase3 = increasing
    long dp0 = nums[0], dp1 = NEG, dp2 = NEG, dp3 = NEG;
    long best = NEG;
    for (int i = 1; i < nums.length; i++) {
        long n0 = nums[i], n1 = NEG, n2 = NEG, n3 = NEG; // dp0 restarts
        if (nums[i] > nums[i - 1]) {                     // increasing step
            n1 = Math.max(dp0, dp1) + nums[i];           // open/extend phase1
            n3 = Math.max(dp2, dp3) + nums[i];           // open/extend phase3
        } else if (nums[i] < nums[i - 1]) {              // decreasing step
            n2 = Math.max(dp1, dp2) + nums[i];           // open/extend phase2
        }
        dp0 = n0; dp1 = n1; dp2 = n2; dp3 = n3;
        best = Math.max(best, dp3);                      // full trionic run
    }
    return best;
}
long long maxSumTrionic(vector<int>& nums) {
    const long long NEG = LLONG_MIN / 4;
    // dpk = best sum of a run ending at i after finishing phase k
    // phase1 = increasing, phase2 = decreasing, phase3 = increasing
    long long dp0 = nums[0], dp1 = NEG, dp2 = NEG, dp3 = NEG;
    long long best = NEG;
    for (int i = 1; i < (int)nums.size(); i++) {
        long long n0 = nums[i], n1 = NEG, n2 = NEG, n3 = NEG; // dp0 restarts
        if (nums[i] > nums[i - 1]) {                          // increasing step
            n1 = max(dp0, dp1) + nums[i];                     // open/extend phase1
            n3 = max(dp2, dp3) + nums[i];                     // open/extend phase3
        } else if (nums[i] < nums[i - 1]) {                   // decreasing step
            n2 = max(dp1, dp2) + nums[i];                     // open/extend phase2
        }
        dp0 = n0; dp1 = n1; dp2 = n2; dp3 = n3;
        best = max(best, dp3);                                // full trionic run
    }
    return best;
}
Time: O(n) Space: O(1)