题目
分析
这道题目最 “难” 的一个点是题目的理解。
给定列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
,为啥输出就是 [1, 1, 4, 2, 1, 1, 0, 0]
?
下面来一个个进行解释。
对于输入 73,它需要 经过一天 才能等到温度的升高,也就是在第二天的时候,温度升高到 74 ,所以对应的结果是 1。
对于输入 74,它需要 经过一天 才能等到温度的升高,也就是在第三天的时候,温度升高到 75 ,所以对应的结果是 1。
对于输入 75,它经过 1 天后发现温度是 71,没有超过它,继续等,一直 等了四天,在第七天才等到温度的升高,温度升高到 76 ,所以对应的结果是 4 。
对于输入 71,它经过 1 天后发现温度是 69,没有超过它,继续等,一直 等了两天,在第六天才等到温度的升高,温度升高到 72 ,所以对应的结果是 2 。
对于输入 69,它 经过一天 后发现温度是 72,已经超过它,所以对应的结果是 1 。
对于输入 72,它 经过一天 后发现温度是 76,已经超过它,所以对应的结果是 1 。
对于输入 76,后续 没有温度 可以超过它,所以对应的结果是 0 。
对于输入 73,后续 没有温度 可以超过它,所以对应的结果是 0 。
好了,理解了题意我们来思考如何求解。
1,最简单的方式是暴力求解,遍历每一个元素,然后再从当前元素往后找比它大的,找到之后记录下他俩位置的差值,然后停止内层循环,如果没找到默认为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;
}
2,暴力求解毕竟效率不高,我们还可以只用栈来解决,这个栈中存放的是数组元素的下标,我们画个图看下
代码如下
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;
}
3,我们还可以把栈改为数组的形式
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;
}
4,这题我们还可以参照第84. 柱状图中最大的矩形
来看一下代码
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;
}
5,最后一种解法,这种更厉害,从后面开始查找,效率更高,击败了100%的用户,代码中有注释,大家自己看
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;
}
//然后我们让j往后挪res[j]个单位,找到那个值,再和第i个元素比较
j += res[j];
}
}
}
return res;
}