【单调栈】[739. 每日温度]

【单调栈】739. 每日温度

给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。

示例 1:

输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]

示例 2:

输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]

示例 3:

输入: temperatures = [30,60,90]
输出: [1,1,0]

提示:

  • 1 <= temperatures.length <= 105
  • 30 <= temperatures[i] <= 100
解法一:递推

执行用时:8 ms, 在所有 Java 提交中击败了99.42%的用户

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        var len = temperatures.length;
        var dp = new int[len];
        
        for(var i = len - 1; i >= 0; i--) {
            var day = 1;
            while(i + day < len 
                && dp[i+day] != 0
                && temperatures[i+day] <= temperatures[i]) {
                day += dp[i+day];
            }

            if(i + day < len && temperatures[i+day] > temperatures[i]) {
                dp[i] = day;
            }
        }

        return dp;
    }
}
解法二:哈希

执行用时: 493 ms

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        var len = temperatures.length;
        var dp = new int[len];
        var map = new HashMap<Integer, Integer>();

        for(var i = len - 1; i >= 0; i--) {
            
            var dumy = Integer.MAX_VALUE;
            var entries = map.entrySet();

            for(var entry : entries) {
                if(entry.getKey() > temperatures[i]) {
                    dumy = Math.min(dumy, entry.getValue() - i);
                }
            }

            map.put(temperatures[i], i);
            dp[i] = dumy == Integer.MAX_VALUE ? 0 : dumy;
        }
        return dp;
    }
}

执行用时: 28 ms

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int[] ans = new int[temperatures.length];
        int[] hash = new int[101];

        for(int i = temperatures.length - 1; i >= 0; i--) {
            int tem = temperatures[i];
            hash[tem] = i;
            int min = Integer.MAX_VALUE;
            for(int j = tem; j<= 100; j++) {
                if(hash[j] > i) {
                    min = Math.min(min, hash[j] - i);
                }
            }
            ans[i] = (min == Integer.MAX_VALUE ? 0 : min);
        }

        return ans;
    }
}
⭐ 解法三:单调栈

​ 使用栈保存大于当前元素且位于其左边元素的下标,为了保持这个特性,应:

  • 如果栈顶元素的值大于等于当前值,则应该将当前值入栈
  • 否则出栈栈中小于当前值的元素,并更新返回数组,当前值即为第一个大于它的右边元素
class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        var len = temperatures.length;
        // 推荐使用双端队列来实现栈和队列
        Deque<Integer> stack = new LinkedList<>();
        var res = new int[len];
        stack.push(0);
        for(var i = 0; i < len; i++) {
            while(!stack.isEmpty() 
                  && temperatures[i] > temperatures[stack.peek()]) {
                var pos = stack.pop();
                res[pos] = i - pos;
            }
            stack.push(i);
        }
        return res;
    }
}

​ 单调栈适用情景:通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。时间复杂度为O(n)。

posted @ 2023-05-11 10:58  Tod4  阅读(45)  评论(0编辑  收藏  举报