【LeetCode】739.每日温度(5种方法,详细图解)

题目

链接

image-20200710223721212

分析

这道题目最 “难” 的一个点是题目的理解。

给定列表 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。

微信截图_20200611104024.png
微信截图_20200611104034.png

    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,暴力求解毕竟效率不高,我们还可以只用栈来解决,这个栈中存放的是数组元素的下标,我们画个图看下

微信截图_20200611131851.png
微信截图_20200611131905.png
微信截图_20200611131914.png
微信截图_20200611131924.png
微信截图_20200611131933.png
微信截图_20200611131941.png
微信截图_20200611131949.png

代码如下

    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%的用户,代码中有注释,大家自己看

微信截图_20200611134941.png

    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;
    }
复制代码
分类:
后端
标签: