每日一道算法题LeetCode739:Daily Temperature(每日温度)

每日温度

  • 题目
  • 分析
  • 题解
    • 暴力求解
    • 递减栈
    • 暴力求解改进
  • 总结

题目

leetcode 739
题目链接:link.
请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。

例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。

提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。

分析

题目写的很花里胡哨,但是究其本质,就是要找每个数与下一个比它大的数的距离,如果后面没有比它大的数,结果就为0。

题解

暴力求解

看完题目,很容易就想到暴力求解,使用双重循环,实现很容易,但是时间空间都浪费了。代码如下:

    public static int[] dailyTemperatures(int[] T) {
        int[] result = new int[T.length];
        for (int i = 0; i < T.length; i++) {
            for(int j = i; j < T.length; j++) {
                if(T[j]>T[i]){
                    result[i] = j-i;
                    break;   // 找到之后就直接break
                }
                if(j == T.length-1 && T[j]<=T[i]) break;
            }
        }
        return result;
    }

递减栈

写完暴力法,很久都没有想到有啥其他方法(还是我菜),后来看了一下题解,一看到递减栈三个字,恍然大悟,实现下来也不难,但是只需要一次循环,时间复杂的O(n),代码如下:

	// 维护一个递减栈,上面的数始终比下面的数小,
	// 栈里只用存数的序号,每次遍历到一个数,
	// 从栈顶向栈底依次比较,碰到比本数大的数就将本数入栈
    public static int[] dailyTemperatures(int[] T){
        if (T == null || T.length == 0) return new int[0];
        Stack<Integer> stack = new Stack<>();
        int[] result = new int[T.length];

        for (int i = 0; i < T.length; i++) {
            while(!stack.empty() && T[i] > T[stack.peek()]){
                int index = stack.pop();
                result[index] = i - index;
            }
            stack.push(i);
        }
        return result;
    }

暴力求解改进

暴力求解的问题就是没有用到前面获得的数据,这个改进从后往前遍历,这样每次向后搜寻的时候,可以利用已经获得的信息进行跳过一些无用的循环,用时缩短很多,超过90+%。代码如下:

public static int[] dailyTemperatures(int[] T){
        int[] result = new int[T.length];
        for (int i = T.length-2; i >=0 ; i--) {   //从后往前
            int j = i+1;
            while (j < T.length){
                if(T[j]>T[i]){     // 大于直接设置结果
                    result[i] = j-i;
                    break;
                }
                else if(result[j]==0){   // 此时j <= i,并且j后没有比j大的值,那么一定没有比i大的值,直接设为0
                    break;
                }
                else{
                    j += result[j];   // 跳跃到下一个较大值,节省时间
                }
            }
        }
        return result;
    }

总结

这个题不算很难,主要题解还是使用递减栈,只是比较难想到(可能是因为我菜吧),至于第三种方法还是比较好理解的,就是一个小小的优化,但是时间上的提升很大。

你可能感兴趣的:(每日一道算法题LeetCode739:Daily Temperature(每日温度))