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;
}


在这里插入图片描述

posted @ 2020-09-24 22:02  数据结构和算法  阅读(101)  评论(0编辑  收藏  举报