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 <= 800001 <= 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