382,每日温度的5种解题思路
想了解更多数据结构以及算法题,可以关注微信公众号“数据结构和算法”,每天一题为你精彩解答。也可以扫描下面的二维码关注
请根据每日气温列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
例如
给定一个列表
[73, 74, 75, 71, 69, 72, 76, 73]
你的输出应该是
[1, 1, 4, 2, 1, 1, 0, 0]。
说明:
73的时候只需要等1天,温度是74比73大。
74的时候只需要等1天,温度是75比74大。
75的时候只需要等4天,温度是76比75大。
……
暴力求解
看到这道题我们首先想到的是暴力求解。他的原理是遍历每一个元素,然后再从当前元素往后找比它大的,找到之后记录下他俩位置的差值,然后停止内层循环,如果没找到默认为0。我们画个图来看一下
看明白了上面的分析过程,代码就容易多了,我们来看下
public int[] dailyTemperatures(int[] T) {
int length = T.length;
int[] res = new int[length];
for (int i = 0; i < length; i++) {
for (int j = i + 1; j < length; j++) {
if (T[j] > T[i]) {
res[i] = j - i;
break;
}
}
}
return res;
}
使用栈解决
暴力求解,效率并不高,我们还可以使用栈来解决,栈存储的是元素的下标,不是元素的值。他的原理就是我们遍历到每个元素的时候用它和栈顶(栈不为空,如果为空直接入栈)元素比较,如果比栈顶元素小就把它对应的下标压栈,如果比栈顶元素大,说明栈顶元素遇到了右边比它大的,然后栈顶元素出栈,在计算下标的差值……重复这样计算。我们就还用上面的数据[73, 74, 75, 71, 69, 72, 76, 73]画个图来看下
搞懂了上面的分析过程我们再来看代码
public int[] dailyTemperatures(int[] T) {
Stack<Integer> stack = new Stack<>();
int[] ret = new int[T.length];
for (int i = 0; i < T.length; i++) {
while (!stack.isEmpty() && T[i] > T[stack.peek()]) {
int idx = stack.pop();
ret[idx] = i - idx;
}
stack.push(i);
}
return ret;
}
我们还可以用数组替换栈
public int[] dailyTemperatures(int[] T) {
int[] stack = new int[T.length];
int top = -1;
int[] res = new int[T.length];
for (int i = 0; i < T.length; i++) {
while (top >= 0 && T[i] > T[stack[top]]) {
int idx = stack[top--];
res[idx] = i - idx;
}
stack[++top] = i;
}
return res;
}
参照第379题
这题和第379题有非常相似的地方,如果看过379,柱状图中最大的矩形(难),这题就非常容易了,代码也非常相似,这个栈中元素所对应值的顺序从栈底到栈顶是递减的,和379题正好相反,我们来看下代码
public int[] dailyTemperatures(int[] T) {
int length = T.length;
Stack<Integer> stack = new Stack<>();
int[] res = new int[length];
for (int i = 0; i < length; i++) {
int h = T[i];
if (stack.isEmpty() || h <= T[stack.peek()]) {
stack.push(i);
} else {
int top = stack.pop();
res[top] = i - top;
i--;
}
}
return res;
}
剪枝
最后一种解法效率也是非常高的,代码中有注释,就不在过多解释,有兴趣的可以看下
public int[] dailyTemperatures(int[] T) {
int[] res = new int[T.length];
//从后面开始查找
for (int i = res.length - 1; i >= 0; i--) {
int j = i + 1;
while (j < res.length) {
if (T[j] > T[i]) {
//如果找到就停止while循环
res[i] = j - i;
break;
} else if (res[j] == 0) {
//如果没找到,并且res[j]==0。说明第j个元素后面没有
//比第j个元素大的值,因为这一步是第i个元素大于第j个元素的值,
//那么很明显这后面就更没有大于第i个元素的值。直接终止while循环。
break;
} else {
//如果没找到,并且res[j]!=0说明第j个元素后面有比第j个元素大的值,
//然后我们让j往后挪res[j]个单位,找到那个值,再和第i个元素比较
j += res[j];
}
}
}
return res;
}