LeetCode Hot 100-739每日温度

每日温度

题目描述

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

这一题说白了就是遍历数组,找数组中每个元素右边第一个比他大的元素,对应的值就是下标的差,如下表

元素向右第一个比他大的值下标差
73741-0=1
74752-1=1
75746-2=4
71725-3=2
69725-4=1
72766-5=1
76-0
73-0

我用的是暴力解法,果然没有过,贴上我的代码

class Solution:
    def dailyTemperatures(self, T: List[int]) -> List[int]:
        result = []
        if not T:
            return
        previous = 0
        tmp = 0
        for i in range(len(T)):
            has_bigger = False
            if previous < T[i]:
                left = i + 1
            else:
                left = tmp
            for j in range(left, len(T)):
                if T[j] > T[i]:
                    has_bigger = True
                    result.append(j - i)
                    tmp = j
                    break
            if not has_bigger:
                result.append(0)
        return result

然后熟练的点击了解题

发现了一个单调栈的东西

  • 单调栈
  • 作用
    可以以 O(1) 的时间复杂度得知某个位置左右两侧比他大(或小)的数的位置,当你需要高效率获取某个位置左右两侧比他大(或小)的数的位置的的时候就可以用到单调栈。

百度了一下还有一个类似的题目,也贴出来

问题描述
地上从左到右竖立着 n 块木板,从 1 到 n 依次编号,如下图所示。我们知道每块木板的高度,在第 n 块木板右侧竖立着一块高度无限大的木板,现对每块木板依次做如下的操作:对于第 i 块木板,我们从其右侧开始倒水,直到水的高度等于第 i 块木板的高度,倒入的水会淹没 ai 块木板(如果木板左右两侧水的高度大于等于木板高度即视为木板被淹没),求 n 次操作后,所有 ai 的和是多少。如图上所示,在第 4 块木板右侧倒水,可以淹没第 5 块和第 6 块一共 2 块木板,a4 = 2。
在这里插入图片描述

暴力求解,是不是很像?复杂度是O(n²),两次循环
例如现在存在5块木板
每块木板从左至右高分别为
10,5,8,12,6
从第一块木板(高度为10)右侧开始倒水,当水到达第四块木板(高度为12)时,可以淹没第一块木板
即第一块木板至第四块木板之间的木板数量,即4-1-1 = 2,a1 = 2;
也就是说:寻找在第 i 个木板右边第一个比它大的木板j,ai 就等于木板 i 和木板 j 之间的木板数
同理得到
a2=0
a3=0
a4=1
a5=0
sum = a1 + a2 +a3 +a4 +a5 = 3

单调栈求解
单调栈来求解的话,复杂度是O(n)
结合单调栈的性质:使用单调栈可以找到元素向左遍历第一个比他小的元素,也可以找到元素向左遍历第一个比他大的元素。
顾名思义,单调栈就是栈内元素单调递增或者单调递减的栈,这一点和单调队列很相似,但是单调栈只能在栈顶操作。
单调栈有以下两个性质:
1、若是单调递增栈,则从栈顶到栈底的元素是严格递增的。若是单调递减栈,则从栈顶到栈底的元素是严格递减的。
2、越靠近栈顶的元素越后进栈。
单调栈与单调队列不同的地方在于栈只能在栈顶操作,因此一般在应用单调栈的地方不限定栈的大小,否则可能会造成元素无法进栈。
元素进栈过程:对于单调递增栈,若当前进栈元素为e,从栈顶开始遍历元素,把小于e或者等于e的元素弹出栈,直接遇到一个大于e的元素或者栈为空为止,然后再把e压入栈中。对于单调递减栈,则每次弹出的是大于e或者等于e的元素。

数据模拟木板倒水单调栈的入栈计算过程
思路:寻找比栈顶高的木板i,找到就出栈,不是就把木板i入栈,给出循环计数样例 10,5,8,12,6
从左往右扫描

状态操作栈内元素计算
栈空10入栈10-
5比10小5入栈10,5-
8比5大5出栈10a2 = 3-2-1 = 0
8比10小8入栈10,8-
12比8大8出栈10a3 = 4-3-1 = 0
12比10大10出栈-a1 = 4-1-1 = 2
栈空12入栈12-
6比12小6入栈12,6-

扫描完成结束
最后栈的结构是:6,12 栈顶为6
由于最右端竖立着一块高度无限大的木板,即存在第六块木板高度为无穷,所以剩余两块木板的算法如下 a5 = 6-5-1 =0
a4 = 6-4-1 = 1
sum = a1 + a2 +a3 +a4 +a5 = 3
因此本题可以在𝑂(𝑛)的时间内迎刃而解了。

我们再回到leetcode题目上
[73, 74, 75, 71, 69, 72, 76, 73] 从左往右扫描,单调递增的栈

状态操作栈内元素计算
栈空73入栈73-
74比73大73出栈-a1 = 1-0 = 1
栈空74入栈74-
75比74大74出栈-a2 = 2-1 = 1
栈空75入栈75-
71比75小71入栈75,71-
69比71小69入栈75,71,69-
72比69大69出栈75,71a5 = 6-5 = 1
72比71大71出栈75a4 = 6-4 = 2
72比75小72入栈75,72-
76比72大72出栈76a6 = 7-6 = 1
76比75大75出栈-a3 = 7-3 = 4
栈空76入栈76-
73比76小73入栈76,73-

结束扫描
其他栈内元素为0

转换成代码(leetcode python3)

class Solution:
	# 构造一个长len(T)的结果数字result,栈tmp
	# 扫描下一个元素的时候
	# 1. 首先不管怎么样,都是要将元素放到tmp栈中
	# 2. 在入栈之前要循环判断将要入栈的元素是不是比栈顶元素大
	# 	2.1 如果大,则将栈顶元素出栈,并且计算值
	#	2.2 循环判断
    def dailyTemperatures(self, T: List[int]) -> List[int]:
        tmp = []
        result = [0] * len(T)
        for i in range(len(T)):
            while tmp and tmp[-1][1] < T[i]:
                (a, b) = tmp.pop()
                print(i-a)
                result[a] = i - a
            tmp.append((i, T[i]))
        return result

题目来源:力扣(LeetCode)
题目链接:https://leetcode-cn.com/problems/daily-temperatures
参考博客:
https://www.cnblogs.com/tham/p/8038828.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值