Welcome to Subscribe On Youtube

3430. Maximum and Minimum Sums of at Most Size K Subarrays

Description

You are given an integer array nums and a positive integer k. Return the sum of the maximum and minimum elements of all subarrays with at most k elements.

 

Example 1:

Input: nums = [1,2,3], k = 2

Output: 20

Explanation:

The subarrays of nums with at most 2 elements are:

Subarray Minimum Maximum Sum
[1] 1 1 2
[2] 2 2 4
[3] 3 3 6
[1, 2] 1 2 3
[2, 3] 2 3 5
Final Total     20

The output would be 20.

Example 2:

Input: nums = [1,-3,1], k = 2

Output: -6

Explanation:

The subarrays of nums with at most 2 elements are:

Subarray Minimum Maximum Sum
[1] 1 1 2
[-3] -3 -3 -6
[1] 1 1 2
[1, -3] -3 1 -2
[-3, 1] -3 1 -2
Final Total     -6

The output would be -6.

 

Constraints:

  • 1 <= nums.length <= 80000
  • 1 <= k <= nums.length
  • -106 <= nums[i] <= 106

Solutions

Solution 1

  • /**
     * @param {number[]} nums
     * @param {number} k
     * @return {number}
     */
    var minMaxSubarraySum = function (nums, k) {
        const computeSum = (nums, k, isMin) => {
            const n = nums.length;
            const prev = Array(n).fill(-1);
            const next = Array(n).fill(n);
            let stk = [];
    
            if (isMin) {
                for (let i = 0; i < n; i++) {
                    while (stk.length > 0 && nums[stk[stk.length - 1]] >= nums[i]) {
                        stk.pop();
                    }
                    prev[i] = stk.length > 0 ? stk[stk.length - 1] : -1;
                    stk.push(i);
                }
                stk = [];
                for (let i = n - 1; i >= 0; i--) {
                    while (stk.length > 0 && nums[stk[stk.length - 1]] > nums[i]) {
                        stk.pop();
                    }
                    next[i] = stk.length > 0 ? stk[stk.length - 1] : n;
                    stk.push(i);
                }
            } else {
                for (let i = 0; i < n; i++) {
                    while (stk.length > 0 && nums[stk[stk.length - 1]] <= nums[i]) {
                        stk.pop();
                    }
                    prev[i] = stk.length > 0 ? stk[stk.length - 1] : -1;
                    stk.push(i);
                }
                stk = [];
                for (let i = n - 1; i >= 0; i--) {
                    while (stk.length > 0 && nums[stk[stk.length - 1]] < nums[i]) {
                        stk.pop();
                    }
                    next[i] = stk.length > 0 ? stk[stk.length - 1] : n;
                    stk.push(i);
                }
            }
    
            let totalSum = 0;
            for (let i = 0; i < n; i++) {
                const left = prev[i];
                const right = next[i];
                const a = left + 1;
                const b = i;
                const c = i;
                const d = right - 1;
    
                let start1 = Math.max(a, i - k + 1);
                let endCandidate1 = d - k + 1;
                let upper1 = Math.min(b, endCandidate1);
    
                let sum1 = 0;
                if (upper1 >= start1) {
                    const termCount = upper1 - start1 + 1;
                    const first = start1;
                    const last = upper1;
                    const indexSum = (last * (last + 1)) / 2 - ((first - 1) * first) / 2;
                    const constantSum = (k - i) * termCount;
                    sum1 = indexSum + constantSum;
                }
    
                let start2 = upper1 + 1;
                let end2 = b;
                start2 = Math.max(start2, a);
                end2 = Math.min(end2, b);
    
                let sum2 = 0;
                if (start2 <= end2) {
                    const count = end2 - start2 + 1;
                    const term = d - i + 1;
                    sum2 = term * count;
                }
    
                totalSum += nums[i] * (sum1 + sum2);
            }
    
            return totalSum;
        };
    
        const minSum = computeSum(nums, k, true);
        const maxSum = computeSum(nums, k, false);
        return minSum + maxSum;
    };
    
    
  • class Solution {
    public:
        long long minMaxSubarraySum(vector<int>& nums, int k) {
            long long totalMaxMinSum = 0;
            long long windowMaxSum = 0, windowMinSum = 0;
    
            // Format: {idx, num, shares}. Use long long to prevent overflow.
            deque<tuple<int, int, long long>> maxStack, minStack;
    
            for (int endIdx = 0; endIdx < nums.size(); endIdx++) {
                int startIdx = max(0, endIdx - k + 1);
    
                // Window start idx slides by 1: must update stacks' info.
                if (startIdx > 0) {
                    get<2>(maxStack.front())--; // Decrement stack's front num shares.
                    windowMaxSum -= get<1>(maxStack.front());
    
                    // Front num out of window.
                    if (get<0>(maxStack.front()) < startIdx)
                        maxStack.pop_front();
    
                    get<2>(minStack.front())--; // Decrement stack's front num shares.
                    windowMinSum -= get<1>(minStack.front());
    
                    // Front num out of window.
                    if (get<0>(minStack.front()) < startIdx)
                        minStack.pop_front();
                }
    
                long long num = nums[endIdx];
    
                long long maxShares = 1; // Base case.
                windowMaxSum += num;
    
                while (!maxStack.empty() && get<1>(maxStack.back()) <= num) {
                    int prevNum = get<1>(maxStack.back());
                    long long prevShares = get<2>(maxStack.back());
                    maxStack.pop_back();
    
                    maxShares += prevShares; // Max shares transition.
    
                    // Reflect transition in max sum.
                    windowMaxSum += (num - prevNum) * prevShares;
                }
    
                maxStack.push_back({endIdx, num, maxShares});
    
                long long minShares = 1; // Base case.
                windowMinSum += num;
    
                while (!minStack.empty() && get<1>(minStack.back()) >= num) {
                    int prevNum = get<1>(minStack.back());
                    long long prevShares = get<2>(minStack.back());
                    minStack.pop_back();
    
                    minShares += prevShares; // Min shares transition.
    
                    // Reflect transition in min sum.
                    windowMinSum += (num - prevNum) * prevShares;
                }
    
                minStack.push_back({endIdx, num, minShares});
    
                totalMaxMinSum += windowMaxSum + windowMinSum;
            }
    
            return totalMaxMinSum;
        }
    };
    
  • class Solution:
        def minMaxSubarraySum(self, nums: list[int], k: int) -> int:
            subarrays_max_min_sum = 0
    
            max_stack: deque[list[int]] = deque([])  # Format: [idx, num, shares].
            subarrays_max_sum = 0
    
            min_stack: deque[list[int]] = deque([])  # Format: [idx, num, shares].
            subarrays_min_sum = 0
    
            for end_idx, num in enumerate(nums):
                start_idx = max(0, end_idx - k + 1)
    
                # Window start idx slides by 1: must update stacks' info.
                if start_idx > 0:
                    max_stack[0][2] -= 1  # Decrement stack's front num shares.
                    subarrays_max_sum -= max_stack[0][1]
    
                    if max_stack[0][0] < start_idx:  # Front num out of window.
                        max_stack.popleft()
    
                    min_stack[0][2] -= 1  # Decrement stack's front num shares.
                    subarrays_min_sum -= min_stack[0][1]
    
                    if min_stack[0][0] < start_idx:  # Front num out of window.
                        min_stack.popleft()
    
                max_shares = 1  # Base case.
                subarrays_max_sum += num
    
                while max_stack and max_stack[-1][1] <= num:
                    _, prev_num, prev_shares = max_stack.pop()
    
                    max_shares += prev_shares  # Max shares transition.
    
                    # Reflect transition in max sum.
                    subarrays_max_sum += (num - prev_num) * prev_shares
    
                max_stack.append([end_idx, num, max_shares])
    
                min_shares = 1  # Base case.
                subarrays_min_sum += num
    
                while min_stack and min_stack[-1][1] >= num:
                    _, prev_num, prev_shares = min_stack.pop()
    
                    min_shares += prev_shares  # Min shares transition.
    
                    # Reflect transition in min sum.
                    subarrays_min_sum += (num - prev_num) * prev_shares
    
                min_stack.append([end_idx, num, min_shares])
    
                subarrays_max_min_sum += subarrays_max_sum + subarrays_min_sum
    
            return subarrays_max_min_sum
    
    

All Problems

All Solutions