给你一个整数数组 nums (下标从 0 开始)和一个整数 k 。
一个子数组 (i, j) 的 分数 定义为 min(nums[i], nums[i+1], …, nums[j]) * (j - i + 1) 。一个 好 子数组的两个端点下标需要满足 i <= k <= j 。
请你返回 好 子数组的最大可能 分数 。
由题意可知,左边界<=k<=右边界,则我们可以从下标k开始,逐渐向左右边界扩展,找到最大值。
若 m i n ( n u m s [ i ] , n u m s [ i + 1 ] , . . . , n u m s [ j ] ) = m i n ( n u m s [ i − 1 ] , n u m s [ i ] , n u m s [ i + 1 ] , . . . , n u m s [ j ] ) min(nums[i], nums[i+1], ..., nums[j])=min(nums[i-1],nums[i], nums[i+1], ..., nums[j]) min(nums[i],nums[i+1],...,nums[j])=min(nums[i−1],nums[i],nums[i+1],...,nums[j]),则 m i n ( n u m s [ i ] , n u m s [ i + 1 ] , . . . , n u m s [ j ] ) ∗ ( j − i + 1 ) < m i n ( n u m s [ i − 1 ] , n u m s [ i ] , n u m s [ i + 1 ] , . . . , n u m s [ j ] ) ∗ [ j − ( i − 1 ) + 1 ] min(nums[i], nums[i+1], ..., nums[j]) * (j - i + 1)<min(nums[i-1],nums[i], nums[i+1], ..., nums[j]) * [j - (i -1)+ 1] min(nums[i],nums[i+1],...,nums[j])∗(j−i+1)<min(nums[i−1],nums[i],nums[i+1],...,nums[j])∗[j−(i−1)+1],即当 n u m s [ i − 1 ] > = m i n ( n u m s [ i ] , n u m s [ i + 1 ] , . . . , n u m s [ j ] ) nums[i-1]>=min(nums[i], nums[i+1], ..., nums[j]) nums[i−1]>=min(nums[i],nums[i+1],...,nums[j])时,左指针向左移动一定能取到更大值,右指针同理
代码如下:
class Solution {
public int maximumScore(int[] nums, int k) {
/*bg:左指针 ed:右指针 area:最大可能分数 min:对应公式中的min(nums[i], nums[i+1], ..., nums[j])*/
int bg=k,ed=k,area=nums[k],min=nums[k];
/*当左指针未触及到左边界或右指针未触及到右边界时*/
while (bg > 0 || ed < nums.length-1){
/*当左指针未触及到左边界且nums[bg-1]>=min,左指针向左移动一位*/
while (bg>0&&nums[bg-1]>=min){
bg--;
}
/*当右指针未触及到左边界且nums[ed+1]>=min,右指针向右移动一位*/
while (ed<nums.length-1&&nums[ed+1]>=min){
ed++;
}
/*计算并更新分数*/
area=Math.max(area,min*(ed-bg+1));
/*当左指针触及到边界,且右指针未触及到边界,右指针向右移动*/
if((bg<=0&&ed<nums.length-1)){
min=nums[++ed];
/*当右指针触及到边界,且左指针未触及到边界,左指针向左移动*/
}else if(bg>0&&ed>=nums.length-1){
min=nums[--bg];
/*当左右指针均未触及到边界,选择较大的一方移动*/
}else if(bg>0&&ed<nums.length-1){
if(nums[bg-1]>=nums[ed+1]){
min=nums[--bg];
}else{
min=nums[++ed];
}
}
}
return area;
}
}