Problem:1793. 好子数组的最大分数
思路:可以先不考虑k,对于每个nums[i]我们可以求一下他最多能往左右扩展到哪里,对于nums[i+k],(k依次取1,2,3…)如果他>=nums[i]那么我们肯定向右扩展,同理,如果nums[i-k],如果他>=nums[i]那么我们肯定向左扩展增大答案。其实就是找左右两边第一个比当前数小的数的下标,这不就是单调栈吗???然后遍历一遍,这样我们就知道了每个数为最小值的时候的答案了。我们最后在处理k,只要[l,r]区间包含了k我们就更新一下答案,维护答案最大值就OK了。
ps:母题的变形题
Accode:
class Solution {
public:
int maximumScore(vector<int>& nums, int k) {
vector<int> left, right;
int ans = 0;
stack<int> sta;
for (int i = 0; i < nums.size(); i++) {
right.push_back(i);
while (sta.size() && nums[sta.top()] > nums[i]) {
right[sta.top()] = i;
sta.pop();
}
sta.push(i);
}
while(sta.size()) sta.pop();
for (int i = 0; i < nums.size(); i++) {
left.push_back(i);
while (sta.size() && nums[sta.top()]>=nums[i]){
sta.pop();
}
if(sta.size()) left[i] = sta.top();
sta.push(i);
}
for(int i=0;i<nums.size();i++){
int l = left[i],r = right[i];
if(l==i) l=-1;
if(r==i) r=nums.size();
if(k>l && r>k) ans = max(ans,nums[i]*(r-l-1));
}
return ans;
}
};
时间复杂度:$o(n)$
当然还有双指针的解法,就留给大家练手了。