LeetCode——5704. 好子数组的最大分数[Maximum Score of a Good Subarray][困难]——分析及代码[Java]
一、题目
给你一个整数数组 nums (下标从 0 开始)和一个整数 k 。
一个子数组 (i, j) 的 分数 定义为 min(nums[i], nums[i+1], …, nums[j]) * (j - i + 1) 。一个 好 子数组的两个端点下标需要满足 i <= k <= j 。
请你返回 好 子数组的最大可能 分数 。
示例 1:
输入:nums = [1,4,3,7,4,5], k = 3
输出:15
解释:最优子数组的左右端点下标是 (1, 5) ,分数为 min(4,3,7,4,5) * (5-1+1) = 3 * 5 = 15 。
示例 2:
输入:nums = [5,5,4,5,4,1,1,1], k = 0
输出:20
解释:最优子数组的左右端点下标是 (0, 4) ,分数为 min(5,5,4,5,4) * (4-0+1) = 4 * 5 = 20 。
提示:
- 1 <= nums.length <= 10^5
- 1 <= nums[i] <= 2 * 10^4
- 0 <= k < nums.length
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-score-of-a-good-subarray
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、分析及代码
1. 单调栈 + 双指针
(1)思路
根据题意,好子数组为从索引 k 向两侧延伸的数组,其分数取决于区间内的最小值和区间长度。
因此可在数组中索引为 k 的元素两侧,设计 2 个单调栈,存储各个最小值及对应的范围。在此基础上,结合双指针方法,遍历选取左、右区间中下一个较大的最小值(若相等则任意选取)并计算分数。过程中计算得到的分数最大值,就是待求的解。
(2)代码
class Solution {
public int maximumScore(int[] nums, int k) {
int n = nums.length, maxScore = 0;
List<Integer> leftRange = new ArrayList<Integer>();//k左侧单调栈
List<Integer> rightRange = new ArrayList<Integer>();//k右侧单调栈
//向单调栈添加元素
leftRange.add(k);
rightRange.add(k);
for (int i = k - 1; i >= 0; i--) {
if (nums[i] < nums[leftRange.get(leftRange.size() - 1)])
leftRange.add(i);
}
for (int i = k + 1; i < n; i++) {
if (nums[i] < nums[rightRange.get(rightRange.size() - 1)])
rightRange.add(i);
}
//在左、右单调栈上设计双指针,统计分数最大值
int i = 0, j = 0, lenL = leftRange.size(), lenR = rightRange.size();
while (i < leftRange.size() || j < rightRange.size()) {
int l = (i == lenL - 1) ? -1 : leftRange.get(i + 1);//当前左侧最小值对应的左边界
int r = (j == lenR - 1) ? n : rightRange.get(j + 1);//当前右侧最小值对应的右边界
maxScore = Math.max(maxScore, Math.min(nums[leftRange.get(i)], nums[rightRange.get(j)]) * (r - l - 1));//计算score
if (i == lenL - 1 && j == lenR - 1)//双指针均已到达边界
break;
else if (i == lenL - 1)//左单调栈已到达边界
j++;
else if (j == lenR - 1)//右单调栈已到达边界
i++;
else if (nums[l] <= nums[r])//选取左、右区间中下一个较大的最小值,若相等则任意选取
j++;
else
i++;
}
return maxScore;
}
}
(3)结果
执行用时 :11 ms,在所有 Java 提交中击败了 100.00% 的用户;
内存消耗 :48.2 MB,在所有 Java 提交中击败了 100.00% 的用户。
(目前提交用户量不足,暂无排名)
三、其他
暂无。