一、题目描述
原题链接:https://leetcode.cn/problems/daily-temperatures/
题目描述:
给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。
示例 1:
输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]
示例 2:输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]
示例 3:输入: temperatures = [30,60,90]
输出: [1,1,0]
二、解题
方法:单调栈
思路分析:
本题靠栈这一数据结构解决更为轻松,找下一个更大或者更小元素是单调栈题目的标配
我们先来记单调栈的结论,然后再解释为什么
结论:
- 1.栈顶向栈底数据递增是求下一个更大元素,栈顶向栈底递减是求下一个更小元素
- 2.单调栈的作用是记录遍历过的元素,然后与当前遍历的元素进行比较,最后再对遍历过的元素(栈内元素)进行操作
注意:这里我们往栈里存储的是下标,如果需要使用对应的元素,直接T[i]就可以获取。如果要修改对应的值,也可以通过下标找到对应位置。
- 注意弹出的时候应该是当前遍历元素不断和栈内元素进行比较,所以这里应该要有一个循环,直到循环结束后,再将当前遍历元素入栈
- 题目要求如果气温在这之后都不会升高,请在该位置用 0 来代替。所以遍历结束后还留在栈内的就是不会再升高的温度了,我们不对其进行任何操作,在开辟数组的时候将数组元素初始化为0即可
- 开辟数组的时候应该使用malloc,而不是int,因为这是在函数接口内,局部变量会在调用结束后被销毁
代码实现
首先我们来cv一下c语言手撕的栈
typedef int STDataType;
typedef struct Stack
{
int top;
int capacity;
STDataType* a;
}ST;
void StackInit(ST* ps);
void StackDestroy(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);
STDataType StackTop(ST* ps);//获得栈顶元素
int StackSize(ST* ps);
bool StackEmpty(ST* ps);
void StackInit(ST* ps)
{
assert(ps);
ps->capacity = ps->top = 0;//指向最后一个数据的下一个
ps->a = NULL;
}
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
void StackPush(ST* ps, STDataType x)
{
assert(ps);
//当内存满了则需要扩容
if (ps->top == ps->capacity)
{
int newcapacity = (ps->capacity == 0) ? 4 : ps->capacity * 2;
STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity);
if (tmp == NULL)
{
perror("malloc fail\n");
return;
}
else
{
ps->capacity = newcapacity;
ps->a = tmp;
}
}
//没满就直接压栈即可
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
STDataType StackTop(ST* ps)//获得栈顶元素
{
assert(ps);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
以下为题解
int* dailyTemperatures(int* temperatures, int temperaturesSize, int* returnSize){
//数组初始化
int* result = (int*)malloc(sizeof(int) * temperaturesSize);
for(int i=0;i<temperaturesSize;i++)
{
result[i]=0;
}
ST st;
StackInit(&st);
*returnSize = temperaturesSize;
StackPush(&st, 0);
for (int i = 1;i < temperaturesSize;i++)
{
//小于等于栈顶元素直接入栈
if (temperatures[i] <= temperatures[StackTop(&st)])
{
StackPush(&st, i);
}
else
{
//当前遍历元素大于栈顶元素,将遍历元素减去栈顶元素后放入数组里,直到栈为空
while (!StackEmpty(&st) && temperatures[i] > temperatures[StackTop(&st)])
{
//后-前
result[StackTop(&st)] = i - StackTop(&st);
StackPop(&st);
}
StackPush(&st, i);
}
}
return result;
}
三、总结
本道题目为单调栈裸题,还有不少的变形题。
希望大家能仔细体会单调栈的用法以及原理,然后再去突破其他几道单调栈的题目
下一个更大元素I
下一个更大元素II