题目描述
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int n = temperatures.length;
int[] res = new int[n];
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (temperatures[j] > temperatures[i]) {
res[i] = j - i;
break;
}
}
}
return res;
}
}
- 时间复杂度: O ( n 2 ) O(n^2) O(n2)
- 时间复杂度: O ( 1 ) O(1) O(1) (忽略res数组)
复杂版在求数组/队列中 左边(或右边)下一个最大值(或最小值)时,使用单调栈是一个非常不错的解法。
由于本题目是求数组中“右边第一个比当前元素大”的节点,所以这里采用的单调栈为:
- 从栈顶到栈低 --> nums[index]单调递增;
- 栈中存的是temperatures下标i
思路:
- 遍历 t e m p e r a t u r e s temperatures temperatures 中所有元素,设当前下标为 i i i;
- 若当前stack为空,则直接将 i i i入栈,就完事了;
- 否则,若以当前栈顶元素(由于栈中存放的是下标,其实是
t
e
m
p
e
r
a
t
u
r
e
s
[
s
t
a
c
k
.
p
e
e
k
(
)
]
temperatures[stack.peek()]
temperatures[stack.peek()])
<=
当前元素 t e m p e r a t u r e s [ i ] temperatures[i] temperatures[i],则不会破坏单调性,直接将i
入栈,即可; - 否则,若栈顶元素(同3解释)
>
当前元素 t e m p e r a t u r e s [ i ] temperatures[i] temperatures[i],此时“单调性”被破坏,需要d栈维护“单调性”;- 若当前栈非空,且
temperatures[i] > temperatures[stack.peek()
,则需要d栈; - 此时(单调性失效),当前元素
t
e
m
p
e
r
a
t
u
r
e
s
[
i
]
temperatures[i]
temperatures[i] 是栈中所有使得“单调性失效”元素的 右边第一个比它大的节点,则需要在d栈时在
r
e
s
res
res 中记录之,即
res[index] = i - index;
- 若当前栈非空,且
两点注意
- 栈中存放的是下标 i i i,比较时应该是 t e m p e r a t u r e s [ i ] < = t e m p e r a t u r e s [ t o p ] temperatures[i] <= temperatures[top] temperatures[i]<=temperatures[top],而不是 t e m p e r a t u r e s [ i ] < = t o p temperatures[i] <= top temperatures[i]<=top;
- 在d栈维护单调性时(while循环中),循环条件必须为
temperatures[i] > temperatures[stack.peek()]
,而不是temperatures[i] > temperatures[top]
此时,d栈后栈顶元素是动态变化的!!!
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
if (temperatures.length < 1) return new int[]{};
int[] res = new int[temperatures.length];
// 从栈顶到栈低 --> nums[index]单调递增
// 栈中存的是temperatures下标i
Deque<Integer> stack = new LinkedList<>();
for (int i = 0; i < temperatures.length; i++) {
if (stack.isEmpty()) {
stack.push(i);
continue;
}
int top = stack.peek();
// 仍然(非严格)单调增,直接入栈
if (temperatures[i] <= temperatures[top]) { // 注意:不是 <= top
stack.push(i);
} else { // >
while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) { // 不能temperatures[i] > top
int index= stack.pop();
// 记录
res[index] = i - index;
}
// 当前元素下标入栈
stack.push(i);
}
}
return res;
}
}
- 时间复杂度: O ( n ) O(n) O(n)
- 时间复杂度: O ( n ) O(n) O(n) (忽略res数组)
精简版可见单调栈其实是“用空间换时间”!
以上代码存在冗余部分,可精简如下:
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
if (temperatures.length < 1) return new int[]{};
int[] res = new int[temperatures.length];
// 单调栈:从栈顶到栈低 --> nums[index]单调递增,栈中存的是temperatures下标i
Deque<Integer> stack = new LinkedList<>();
for (int i = 0; i < temperatures.length; i++) {
while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) { // 不能temperatures[i] > top
int index = stack.pop();
res[index] = i - index; // 记录
}
// 当前元素入栈
stack.push(i);
}
return res;
}
}
时、空复杂度不变。
题目描述
思路:
- 将链表转化为数组;
- 然后,同739. 每日温度一样了
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public int[] nextLargerNodes(ListNode head) {
// 将链表转化为数组
List<Integer> nums = new ArrayList<>();
while (head != null) {
nums.add(head.val);
head = head.next;
}
System.out.println(nums);
int n = nums.size();
int[] res = new int[n];
// 单调栈:从栈顶到栈低递增(非严格),栈中存放的是nums的下标
Deque<Integer> stack = new LinkedList<>();
for (int i = 0; i < n; i++) {
if (stack.isEmpty()) {
stack.push(i);
continue;
}
if (nums.get(i) <= nums.get(stack.peek())) {
stack.push(i);
} else {
// 维护单调性(其中,栈中存放的是nums的下标)
while (!stack.isEmpty() && nums.get(stack.peek()) < nums.get(i)) {
System.out.println("--------------");
System.out.println("stack = " + stack);
// d栈并记录
int index = stack.poll();
// 当前元素是单调栈中需要d栈单调性的节点的右边第一个更大值
res[index] = nums.get(i);
System.out.println("i = " + i);
System.out.println("index = " + index);
}
// 当前元素入栈(保证单调增)
stack.push(i);
}
}
return res;
}
}
参考:
- 单调栈详解
- Carl题解
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)