代码随想录Day62 | 739.每日温度 496.下一个更大元素 I
单调栈
用于解决一个一维数组中,要寻找任意一个元素的右边或者左边第一个比自己大或者小的元素的位置,就可以考虑单调栈。
本质是在遍历数组中,需要用一个栈来记录右边(或者左边)第一个比当前元素大(或者小)的元素位置。
单调栈需要明确的几个要点
- 单调栈里存放的元素是什么
- 单调栈里的元素是递增还是递减
顺序的描述应该是以从栈头到栈底的顺序
如果求一个元素右边第一个更大元素,单调栈就是递增的,如果求一个元素右边第一个更小元素,单调栈就是递减的- 单调栈的主要判断条件
当前元素小于栈顶元素
当前元素等于栈顶元素
当前元素大于栈顶元素
739.每日温度
文档讲解:代码随想录
视频讲解: 单调栈,你该了解的,这里都讲了!LeetCode:739.每日温度
状态
首先考虑暴力解法最后超时了,利用双重循环,当第二层循环中遇到比外层循环i所对应的温度高时记录,然后跳出更新返回结果。
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
vector<int> res(temperatures.size(),0);
int count = 0;
for(int i = 0;i<temperatures.size();i++)
{
int day = temperatures.size();
for(int j = i+1;j<temperatures.size();j++)
{
if(temperatures[j] > temperatures[i])
{
day = j;
break;
}
}
if(day == temperatures.size()) res[i] = 0;
else res[i] = day-i;
}
return res;
}
};
暴力解法
添加一个辅助数组next,用来记录每个温度第一次出现的下标,最开始初始化为无穷大。
反向遍历温度列表,在next数组中寻找比当前温度高的每个温度第一次出现的下标。然后记录其中的最小值minval,如果该最小值不再是无穷大,那么说明等待天数为minval - i,然后更新next[temperatures[i]] = i
由于是反向遍历,所以当考虑temperatures[i]时只有温度列表在i之后的值被访问更新过,如果next[j]不为无穷大那么就会找到比temperatures[i]大的温度。而由于next[i]记录的是温度第一次出现的下标,所以后续出现相同的温度会被覆盖更新
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
vector<int> res(temperatures.size(),0);
vector<int> next(101,INT_MAX);
for(int i = temperatures.size()-1;i>=0;i--)
{
int minval = INT_MAX;
for(int j = temperatures[i]+1;j<=100;j++)
{
minval = min(minval,next[j]);
}
if(minval != INT_MAX)
{
res[i] = minval - i;
}
next[temperatures[i]] = i;
}
return res;
}
};
单调栈
- 单调栈里面存放的元素
就是当前元素的下标 - 单调栈是递增还是递减
应该是采用递增的,即从栈头到栈底应该是递增的。
对于数组我们从前向后遍历,然后不断将下标压入栈中,如果下标元素比当前栈中的元素大,那么就先弹出,再压入
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
vector<int> res(temperatures.size(),0);
stack<int> check;
check.push(0);
for(int i = 1;i<temperatures.size();i++)
{
while(!check.empty() && temperatures[i] > temperatures[check.top()])
{
res[check.top()] = i - check.top();
check.pop();
}
//当前元素小于或者等于目前栈顶元素
check.push(i);
}
return res;
}
};
496.下一个更大元素I
文档讲解:代码随想录
视频讲解: 单调栈,套上一个壳子就有点绕了| LeetCode:496.下一个更大元素
状态
本质上就是找nums2中一些数的右边第一个大值,我们可以利用map来存储nums1里面的数据这样当我们使用单调栈去求nums2中元素右边的第一个大值时,当当前元素是nums1中的元素我们就对结果数组res进行更新。
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
vector<int> res(nums1.size(),-1);
unordered_map<int,int> nums2map;
if (nums1.size() == 0) return res;
//利用map来存储下标 方便查找
for(int i = 0;i<nums1.size();i++)
{
nums2map[nums1[i]] = i;
}
stack<int> check;
check.push(0);
//寻找nums2中每个元素的右边第一个大值
for(int i = 1;i<nums2.size();i++)
{
//如果小于等于此时的栈顶元素 压入
if(nums2[i] <= nums2[check.top()])
{
check.push(i);
}
else
{
//当大于此时的栈顶元素
while(!check.empty()&&nums2[i] > nums2[check.top()])
{
//判断栈顶元素是否是nums1中的值
if(nums2map.count(nums2[check.top()]) > 0)
{
//如果是就记录更新res
//nums2map[nums2[check.top()]] 下标
res[nums2map[nums2[check.top()]]] = nums2[i];
}
//弹出当前栈顶
check.pop();
}
//压入大值
check.push(i);
}
}
return res;
}
};