LeetCode-每日温度DailyTemperatures

题目要求

/**
 * @author yangshuo
 * @date 2020/3/20 15:50
 *
 * 根据每日 气温 列表,请重新生成一个列表,对应位置的输出是需要再等待多久温度才会升高超过该日的天数。
 * 如果之后都不会升高,请在该位置用 0 来代替。
 *
 * 例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],
 * 你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
 *
 * 提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。
 *
 */

初步解法:

看完题目我的第一想法是设置一个栈,遍历全部温度,依次入栈,在遍历的过程中,

1、将当前温度与栈顶温度做对比,如果大于当前温度就入栈

2、如果小于,就说明气温升高了,用当前序号减去栈顶温度的序号就是要求的天数

3、栈顶温度出栈,继续和下一个栈顶温度做比对,直到为空,或者栈顶温度大于当前温度

4、遍历一遍数组就能找出所有温度升高超过该日的天数

代码如下:

public int[] dailyTemperatures(int[] T) {

        if (T == null || T.length <= 0){
            return null;
        }
        int length = T.length;
        int[] days = new int[length];
        if (T.length == 1){
            return days;
        }

        Stack stack = new Stack<>();
        // 先把第一个温度压入
        Temperature temperature = new Temperature(0,T[0]);
        stack.add(temperature);

        for (int i = 1; i < length; i++){
            int t = T[i];
            while (!stack.isEmpty()){
                Temperature peek = stack.peek();
                if (peek.value < t){
                    // 说明找到了首个温度升高的时候,序号相减就是间隔天数
                    days[peek.index] = i - peek.index;
                    stack.pop();
                }else{
                    // 说明没有找到,退出栈的循环
                    break;
                }
            }
            // 将最新的温度压入
            stack.add(new Temperature(i,t));
        }
        return days;
    }

    // 为了保存序号,设置了一个对象
    class Temperature{
        private int index;
        private int value;

        public Temperature(int index, int value){
            this.index = index;
            this.value = value;
        }
    }

 

LeetCode-每日温度DailyTemperatures_第1张图片

LeetCode-每日温度DailyTemperatures_第2张图片

虽然执行时间还可以,但是内存消耗很糟糕,继续优化

因为第一个最大数的限制,所以保证了,他的状态是可以存在最终的数组中的。

优化方案:

1、从倒数第二个数字从后往前遍历

2、当前记为current,作比较的记为after,如果current

3、如果current>after,就令after=after的after,返回第二步

 

public int[] dailyTemperatures(int[] T) {

        if (T == null || T.length <= 0){
            return null;
        }
        int length = T.length;
        int[] days = new int[length];
        if (T.length == 1){
            return days;
        }

        // 从后往前遍历
        for (int i = length -2; i >= 0; i--){
            /**
             * 每次加上后一个的位置值的原因是
             *
             * 如果current大于after,就去看after的第一个大于它的数字在什么位置,是不是比当前大
             * 因为是第一个所以保证了中间不会出现比current还大的
             * 比current还大的,那肯定比after大,比after大的数字出现在中间,只能说明after的时候就已经出错了
             */
            for (int j = i + 1; j < length; j += days[j]){
                int current = T[i];
                int after = T[j];
                // 如果后面的大于当前,说明找到了第一次比他大的位置
                if (after > current){
                    days[i] = j - i;
                    break;
                }
                // 如果等于0说明,后面不会有比current更大的了
                if (days[j] == 0){
                    break;
                }
            }
        }
        return days;

    }

执行结果:

LeetCode-每日温度DailyTemperatures_第3张图片

LeetCode-每日温度DailyTemperatures_第4张图片

微信公众号:二虎程序

LeetCode-每日温度DailyTemperatures_第5张图片

LeetCode-每日温度DailyTemperatures_第6张图片

你可能感兴趣的:(算法,LeetCode)