Trionic Array II

Hard
Watch on YouTube ↗

Solution

class Solution {
    public long maxSumTrionic(int[] nums) {
        int n = nums.length;
        long presum[] = new long[n+1];

        // Build prefix sum array - O(n)
        for(int i=1; i<=n; i++) {
            presum[i] = presum[i-1] + nums[i-1];
        }

        long maxsum = Long.MIN_VALUE;
        int i = 1;

        // Outer loop - O(n^2) worst case
        while(i < n-2) {
            int left = i-1;

            // First increasing part: nums[left...pIndex]
            while(i < n && nums[i] > nums[i-1])
                i++;
            if(i == left+1) {
                i++;
                continue;
            }
            int pIndex = i-1;

            // Decreasing part: nums[pIndex...qIndex]
            while(i < n && nums[i] < nums[i-1]) 
                i++;
            if(i == pIndex+1) {
                i++;
                continue;
            }
            int qIndex = i-1;

            // Second increasing part: nums[qIndex...right]
            while(i < n && nums[i] > nums[i-1])
                i++;
            if(i == qIndex+1) {
                i++;
                continue;
            }
            int right = i-1;

            // Find max sum of trionic subarray [left...right]
            // maxprefixsum: max of presum in range [qIndex+1...right+1]
            // minprefixsum: min of presum in range [left...pIndex-1]
            // Difference gives max sum of any subarray ending in [qIndex...right] and starting in [left...pIndex]
            long maxprefixsum = Long.MIN_VALUE;
            long minprefixsum = Long.MAX_VALUE;
            
            for(int j = left; j < pIndex; j++) {
                minprefixsum = Math.min(minprefixsum, presum[j]); 
            }
            
            for(int j = qIndex+1; j <= right; j++) {
                maxprefixsum = Math.max(maxprefixsum, presum[j+1]); 
            }
            
            maxsum = Math.max(maxsum, maxprefixsum - minprefixsum);
            i = qIndex + 1;
        }

        return maxsum;
    }
}