LeetCode 739 每日温度
思路
给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。
暴力解法
对于每天的问题向后搜索更高的温度。
- 时间复杂度:
单调栈解法
为了找到一个元素右边第一个比自己大的元素,就想到使用单调栈。单调栈的本质是用空间换时间,用一个栈记录我们遍历到的所有元素,就不需要重复去遍历,因此时间复杂度为
使用单调栈时需要明确:
- 单调栈中存放的元素是什么: 单调栈中存放元素的下标,如果需要使用对应的元素,根据下标获取
- 单调栈里元素是递增or递减(从栈顶到栈底) 为了把还没找到右边第一个更大元素的元素中,最先可能找到的元素置顶(栈只能读取栈顶),栈应该是递增的
使用单调栈时有三种情况:
- 遍历元素
temp[i]小于栈顶元素temp[stack.top]:i入栈 - 遍历元素
temp[i]等于栈顶元素temp[stack.top]:i入栈 - 遍历元素
temp[i]大于栈顶元素temp[stack.top]:弹出栈顶直到temp[stack.top]大于等于temp[i],i入栈。把弹出的元素k的answer置为i-k
解法
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int[] answer = new int[temperatures.length];
Stack<Integer> stack = new Stack<>();
stack.push(0);
for (int i = 1; i < temperatures.length; i++) {
if (temperatures[i] <= temperatures[stack.peek()]) {
stack.push(i);
}
else {
while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) {
int k = stack.pop();
answer[k] = i - k;
}
stack.push(i);
}
}
return answer;
}
}
LeetCode 496.下一个更大元素 I
思路
nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。
给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。
对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1 。
返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素 。
本质上本题是要寻找nums2数组中部分元素的下一个更大元素。这一部份需要寻找的元素就是nums1中的元素,返回结果的顺序也要和nums1对应。为了成功对应,且nums1和nums2都是无重复元素的,我们可以用一个Map去映射nums1的元素和下标。
本题单调栈中存储元素在nums2中的下标,递增。
考虑使用单调栈时情况:
- 如果
nums2[i]小于等于栈顶元素nums2[stack.top]或 栈为空:- 如果
nums2[i]在Map中,i入栈 - 否则,跳过
- 如果
- 如果
nums2[i]大于栈顶元素nums2[stack.top]:- 弹出栈顶元素直到
nums2[i]小于栈顶元素nums2[stack.top] - 对弹出的k,
answer[nums2[k].value]置为nums2[i] - 如果
nums2[i]在Map中,i入栈 - 否则,跳过
- 弹出栈顶元素直到
解法
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
int[] answer = new int[nums1.length];
for (int i = 0; i < answer.length; i++) {
answer[i] = -1;
}
Stack<Integer> stack = new Stack<>();
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums1.length; i++) {
map.put(nums1[i], i);
}
for (int i = 0; i < nums2.length; i++) {
if (stack.isEmpty() || nums2[i] <= nums2[stack.peek()]) {
if (map.containsKey(nums2[i])) {
stack.push(i);
}
}
else {
while (!stack.isEmpty() && nums2[i] > nums2[stack.peek()]) {
int k = stack.pop();
answer[map.get(nums2[k])] = nums2[i];
}
if (map.containsKey(nums2[i])) {
stack.push(i);
}
}
}
return answer;
}
}
LeetCode 503下一个更大元素II
思路
给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。
数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1 。
在LeetCode 739 每日温度的基础上改成了环形数组。依旧使用单调栈存储下标,从栈顶到栈底递增。
区别仅在于对于数组的遍历上,LeetCode 739 每日温度只需要从头到尾遍历一边数组,但本题由于可以通过循环找到前面的元素,需要遍历两次。最后除了数组中最大的元素,其他元素都能找到更大的下一个元素
使用单调栈时有三种情况:
- 遍历元素
nums[i]小于栈顶元素nums[stack.top]:i入栈 - 遍历元素
nums[i]等于栈顶元素nums[stack.top]:i入栈 - 遍历元素
nums[i]大于栈顶元素nums[stack.top]:弹出栈顶直到nums[stack.top]大于等于nums[i],i入栈。把弹出的元素k的answer置为nums[i]
解法
class Solution {
public int[] nextGreaterElements(int[] nums) {
int[] answer = new int[nums.length];
for (int i = 0; i < answer.length; i++) {
answer[i] = -1;
}
Stack<Integer> stack = new Stack<>();
stack.push(0);
for (int i = 1; i < answer.length * 2; i++) {
int index = i % nums.length;
if (nums[index] <= nums[stack.peek()]) {
stack.push(index);
}
else {
while (!stack.isEmpty() && nums[index] > nums[stack.peek()]) {
int k = stack.pop();
answer[k] = nums[index];
}
stack.push(index);
}
}
return answer;
}
}
今日收获总结
今日学习时长3小时。