Maximum Score of a Good Subarray — Problem & Solution
Maximum Score of a Good Subarray solution explained: step-by-step approach, complexity and code in Python, Java, C++ and JavaScript. A hard problem.
Maximum Score of a Good Subarray is a hard coding problem on arrays, two pointers and stack, asked in Amazon, Google and Microsoft interviews.
- Difficulty: Hard
- Topics: Arrays, Two Pointers, Stack, Monotonic Stack
- Asked at: Amazon, Google, Microsoft
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
You are given an integer array nums and an index k. The score of a subarray nums[i..j] is min(nums[i..j]) * (j - i + 1) — its smallest element times its length.
A subarray is good when it contains index k, that is i <= k <= j. Return the maximum score over all good subarrays.
Example 1
Input: nums = [2,6,4,8,3], k = 2
Output: 12
Explanation: `[6,4,8]` scores 4 × 3 = 12, and so does `[6,4,8,3]` with 3 × 4.
Example 2
Input: nums = [7,1,7,7,7], k = 3
Output: 21
Explanation: `[7,7,7]` (indices 2–4) avoids the 1.
Example 3
Input: nums = [5], k = 0
Output: 5
Constraints
1 <= nums.length <= 10^51 <= nums[i] <= 2 * 10^40 <= k < nums.length
Hints for Maximum Score of a Good Subarray
Hint 1
Every good subarray grows outward from index
k. Think of starting with[k, k]and widening it one element at a time.Hint 2
When you widen, the minimum can only stay the same or drop. Which side should you take to keep it as high as possible?
Hint 3
Always extend toward the larger of the two neighbours (
nums[i - 1]vsnums[j + 1]), update the running minimum, and recordmin × lengthafter every step.
How to solve Maximum Score of a Good Subarray
Grow the window from [k, k] greedily, always swallowing the larger neighbour. For every possible minimum value this reaches the widest good window with that minimum, so the best score is seen along the way.
Approach
- Set
i = j = k,cur = nums[k],best = cur. - While the window can still grow: if the left end is at 0, or the right neighbour
nums[j + 1]is larger than the left neighbournums[i - 1], extend right; otherwise extend left. - Update
curto the minimum of the window andbest = max(best, cur × (j - i + 1)). - Return
bestonce the window covers the whole array.
Why it works
Fix a threshold v. The widest good window whose elements are all >= v is the maximal run around k of elements >= v. The greedy never steps past an element smaller than v while a neighbour >= v is still available on the other side, so at some moment its window equals that maximal run — and at that moment its score is at least v times the run's length. Taking v as the minimum of the optimal subarray shows the greedy records a score at least as large as the optimum.
Complexity
- Time —
O(n) - Space —
O(1)
Pitfalls
- Checking only subarrays that start or end at
kmisses windows spreading both ways. - Handle the borders: once one side is exhausted, only the other side can grow.
- The product reaches 2 · 10^9 — near the top of int32, so compute it with care in languages that overflow silently.
Reference solution
Python
from typing import List
def maximumScore(nums: List[int], k: int) -> int:
n = len(nums)
i = j = k
cur = nums[k]
best = cur
while i > 0 or j < n - 1:
if i == 0 or (j < n - 1 and nums[j + 1] > nums[i - 1]):
j += 1
cur = min(cur, nums[j])
else:
i -= 1
cur = min(cur, nums[i])
best = max(best, cur * (j - i + 1))
return bestJava
public static int maximumScore(int[] nums, int k) {
int n = nums.length;
int i = k, j = k;
int cur = nums[k];
long best = cur;
while (i > 0 || j < n - 1) {
if (i == 0 || (j < n - 1 && nums[j + 1] > nums[i - 1])) {
j++;
cur = Math.min(cur, nums[j]);
} else {
i--;
cur = Math.min(cur, nums[i]);
}
best = Math.max(best, (long) cur * (j - i + 1));
}
return (int) best;
}C++
int maximumScore(vector<int>& nums, int k) {
int n = nums.size();
int i = k, j = k;
int cur = nums[k];
long long best = cur;
while (i > 0 || j < n - 1) {
if (i == 0 || (j < n - 1 && nums[j + 1] > nums[i - 1])) {
j++;
cur = min(cur, nums[j]);
} else {
i--;
cur = min(cur, nums[i]);
}
best = max(best, (long long)cur * (j - i + 1));
}
return (int)best;
}JavaScript
var maximumScore = function(nums, k) {
var n = nums.length;
var i = k, j = k;
var cur = nums[k], best = cur;
while (i > 0 || j < n - 1) {
if (i === 0 || (j < n - 1 && nums[j + 1] > nums[i - 1])) {
j++;
cur = Math.min(cur, nums[j]);
} else {
i--;
cur = Math.min(cur, nums[i]);
}
best = Math.max(best, cur * (j - i + 1));
}
return best;
};Also on the editorial tab: C, C#, Go, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 1199 arrays problems · the whole catalogue
Learn the technique: Arrays · Two Pointers Technique