模板问题:Mono Stack/Queue (LeetCode739: Daily Temperatures)
我们之前专们解决过这类问题
https://blog.csdn.net/weixin_44337445/article/details/106157119
现在我们来宏观的复习一下:
所谓的mono stack/queue,就是我们保持stack里面的元素递增或者递减。
也就是说 我们可以随时直到当前元素的PLE或者NLE(previous less element/next less element)元素的位置
以:LC907为例:
Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarray of A.
那么mono stack是如何apply到这上面的呢?
针对每一个元素 我们找他的PLE离A[i]的距离 写到ple[i]中
找他的NLE离A[i]的距离 写到nle[i]中
然后本题的最后的答案就是Sum(A[i] * ple[i] * nle[i]) 意思就是以A[i]作为最小的值的subarray的个数为ple[i]*nle[i]个。
仔细观察下面纯净版的代码:
核心就是构建ple和nle stack
class Solution {
public int sumSubarrayMins(int[] A) {
Stack<int[]> ple = new Stack<>(); //int[0],int[1] = A[i], i
Stack<int[]> nle = new Stack<>();
int[] left = new int[A.length];
int[] right = new int[A.length];
//construct ple
for (int i = 0; i<A.length; i++) {
while (!ple.isEmpty() && ple.peek()[0] >= A[i]) {
ple.pop();
}
left[i] = ple.isEmpty()? i+1: i - ple.peek()[1];
ple.push(new int[]{A[i], i});
}
//construct nle
for (int i = A.length - 1; i>=0; i--) {
while (!nle.isEmpty() && nle.peek()[0] > A[i]) {
nle.pop();
}
right[i] = nle.isEmpty() ? A.length - i: nle.peek()[1] - i;
nle.push(new int[]{A[i], i});
}
int ans = 0;
int mod = 1000000007;
for (int i = 0; i<left.length; i++) {
ans = (ans + A[i] * left[i] * right[i]) % mod;
}
return ans;
}
}
接下来再看看下面的注释版:
class Solution {
public int sumSubarrayMins(int[] A) {
Stack<int[]> ple = new Stack<>(); //int[0],int[1] = A[i], i
Stack<int[]> nle = new Stack<>();
int[] left = new int[A.length];
int[] right = new int[A.length];
//construct ple
for (int i = 0; i<A.length; i++) {
while (!ple.isEmpty() && ple.peek()[0] >= A[i]) { //将大于等于当前值的全部pop,也就是说 只留下第一个小于A【i】的
ple.pop();
}
left[i] = ple.isEmpty()? i+1: i - ple.peek()[1]; //如果是空就说明i前面的都小于i 所以这个长度为(i+1)(因为我们是包含了i的)
ple.push(new int[]{A[i], i}); //push进去当前的
}
//construct nle
for (int i = A.length - 1; i>=0; i--) {
while (!nle.isEmpty() && nle.peek()[0] > A[i]) {
nle.pop();//一直Pop 直到第一个小于等于A[i]的
}
right[i] = nle.isEmpty() ? A.length - i: nle.peek()[1] - i;
nle.push(new int[]{A[i], i}); //跟之前nle的解释一样
}
int ans = 0; //
int mod = 1000000007;
for (int i = 0; i<left.length; i++) {
ans = (ans + A[i] * left[i] * right[i]) % mod;
}
return ans;
}
}
下面来看一下LC739
就是完完全全按照907来的
class Solution {
public int[] dailyTemperatures(int[] T) {
//典型的mono stack问题
//之前我们需要求ple/nle 现在我们需要求next larger element.
//思路上并没有什么不同
LinkedList<int[]> nle = new LinkedList<>();
int n = T.length;
int[] right = new int[n];
for (int i = n - 1; i >= 0; i--) {
while (!nle.isEmpty() && nle.peek()[0] <= T[i]) { //keep pop until find the first one who is larger than T[i]
nle.pop();
}
right[i] = nle.isEmpty() ? 0: nle.peek()[1] - i; //这儿要尤其注意 我们现在要的是长度 如果没有这样的东西存在 就说明没有符合条件的 所哟定为0.
nle.push(new int[]{T[i], i});
}
return right;
}
}

浙公网安备 33010602011771号