class Solution:
def maximumScore(self, nums, k):
n = len(nums)
left = right = k
min_val = nums[k]
max_score = min_val
while left > 0 or right < n - 1:
if left == 0:
right += 1
elif right == n - 1:
left -= 1
elif nums[left - 1] > nums[right + 1]:
left -= 1
else:
right += 1
min_val = min(min_val, nums[left], nums[right])
max_score = max(max_score, min_val * (right - left + 1))
return max_score
class Solution {
public:
int maximumScore(vector<int>& nums, int k) {
int n = nums.size();
int left = k, right = k;
int minVal = nums[k];
int maxScore = minVal;
while (left > 0 || right < n - 1) {
if (left == 0)
++right;
else if (right == n - 1)
--left;
else if (nums[left - 1] > nums[right + 1])
--left;
else
++right;
minVal = min(minVal, min(nums[left], nums[right]));
maxScore = max(maxScore, minVal * (right - left + 1));
}
return maxScore;
}
};
class Solution {
public int maximumScore(int[] nums, int k) {
int n = nums.length;
int left = k, right = k;
int minVal = nums[k];
int maxScore = minVal;
while (left > 0 || right < n - 1) {
if (left == 0) {
right++;
} else if (right == n - 1) {
left--;
} else if (nums[left - 1] > nums[right + 1]) {
left--;
} else {
right++;
}
minVal = Math.min(minVal, Math.min(nums[left], nums[right]));
maxScore = Math.max(maxScore, minVal * (right - left + 1));
}
return maxScore;
}
}
var maximumScore = function(nums, k) {
let n = nums.length;
let left = k, right = k;
let minVal = nums[k];
let maxScore = minVal;
while (left > 0 || right < n - 1) {
if (left === 0) {
right++;
} else if (right === n - 1) {
left--;
} else if (nums[left - 1] > nums[right + 1]) {
left--;
} else {
right++;
}
minVal = Math.min(minVal, nums[left], nums[right]);
maxScore = Math.max(maxScore, minVal * (right - left + 1));
}
return maxScore;
};
You are given an integer array nums
and an integer k
.
Your task is to find the maximum possible score for any subarray that contains the index k
.
The score of a subarray is defined as the minimum value in the subarray multiplied by the length of the subarray.
Key constraints:
k
.k
.k
).
At first glance, it seems we could check every possible subarray containing k
, calculate the minimum value in each, multiply by its length, and keep track of the maximum score found. However, this brute-force approach would be too slow for large arrays because it involves checking many overlapping subarrays and repeatedly finding minimums, which is inefficient.
To optimize, we need a way to efficiently expand the subarray from k
and update the minimum value without re-scanning the whole subarray each time. Instead of checking all possible subarrays, we can start with the smallest subarray (just k
itself), and then expand one element at a time to the left or right, always keeping track of the current minimum and updating the score. At each step, we choose the direction (left or right) that gives us a higher next element, so the minimum value drops as slowly as possible, maximizing the score.
Let's break down the optimized algorithm step by step:
left
and right
, both at k
. This marks the current subarray as just the single element at k
.
minVal
to record the minimum value in the current subarray. Initially, it's nums[k]
.
left
can move left or right
can move right:
left
is at 0, we can only move right
(and vice versa).nums[left - 1]
and nums[right + 1]
. Move in the direction with the larger value, because this will keep our minimum value as high as possible for longer, maximizing the score.minVal
to be the minimum of the current minVal
and the new value included by expanding.minVal * (right - left + 1)
.left
nor right
can expand, return the maximum score found.
This approach works efficiently because each element is considered at most once as the window expands, and we always know the minimum in the current window without needing to scan it.
Let's walk through an example with nums = [1,4,3,7,4,5]
and k = 3
.
left = 3
, right = 3
, minVal = 7
, maxScore = 7
.
nums[2]=3
(left), nums[4]=4
(right). Since 4 > 3, expand right:
right = 4
, minVal = min(7,4)=4
, window is [7,4], score = 4*2=8, maxScore=8
.nums[2]=3
(left), nums[5]=5
(right). 5 > 3, expand right:
right = 5
, minVal = min(4,5)=4
, window is [7,4,5], score = 4*3=12, maxScore=12
.left = 2
, minVal = min(4,3)=3
, window is [3,7,4,5], score = 3*4=12, maxScore=12
.left = 1
, minVal = min(3,4)=3
, window is [4,3,7,4,5], score = 3*5=15, maxScore=15
.left = 0
, minVal = min(3,1)=1
, window is [1,4,3,7,4,5], score = 1*6=6, maxScore=15
.15
.
k
, we scan to find the minimum (O(N) per subarray), and there are O(N2) such subarrays. So total time is O(N3).
k
left and right, at each step moving one pointer and updating the minimum in O(1) time. Overall, each pointer moves at most N times, so the total time is O(N).
The key to solving the "Maximum Score of a Good Subarray" problem efficiently is to avoid brute-force checking all possible subarrays. Instead, by expanding a window from k
and always choosing to include the larger next element, we keep the minimum value high for as long as possible. This greedy approach ensures we consider all the best possible windows in linear time. The algorithm is both efficient and elegant, making use of two pointers and a running minimum to achieve optimal performance.