题一:每日温度
链接https://leetcode-cn.com/problems/daily-temperatures/
请根据每日气温列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
对于题目的意思其实就是要寻找任一个元素的右边第一个比自己大的元素的位置,然后计算距离
例:
IN:
temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
OUT:
[1, 1, 4, 2, 1, 1, 0, 0]
思路:
一.
最简单的方法,从左遍历到右,寻找后面第一个大于当前的数,然后下标相减。
但是题目给的列表长度为[1, 30000],而且此方法的时间复杂度为O(n²),所以当列表长度过长时,就会超出时间限制。
class Solution(object):
def dailyTemperatures(self, T):
"""
:type T: List[int]
:rtype: List[int]
"""
size = len(T)
days = [0] * size
for i in range(size):
for j in range(i + 1, size):
if T[i] < T[j]:
days[i] = j - i
break
return days
二.
应用单调栈,本人第一次接触单调栈数据结构,所以从网上查询了资料,这篇文章说得非常详细,不懂的小伙伴可以看下,受益匪浅。
https://blog.csdn.net/lucky52529/article/details/89155694
简单来说,单调栈是一种有序的,符合单调特征(单调递增/单调递减)的一种数据结构。
1.建立栈,存储各天温度对应的下标(从栈底到栈顶温度依次递减,下标在栈中表示尚未找到下次更高温度的下标);
2.判断栈中是否为空,为空则直接将 T[i] 的下标存储进去,不为空则判断栈顶的下标 stack[-1] 所对应的温度 T [stack[i]] 是否小于 T[i] ,小于则移除 stack[-1] ,并计算天数 i - stack[-1] , 重复上述操作直到栈为空或者 T[stack[i]] > T[i]结束。
class Solution(object):
def dailyTemperatures(self, T):
"""
:type T: List[int]
:rtype: List[int]
"""
size = len(T)
days = [0 for _ in range(size)]
stack = [] # 存储下标 单调递减栈
for i in range(size):
while stack and T[stack[-1]] < T[i]:
output = stack.pop()
days[output] = i - output
stack.append(i)
return days
题二:计算器
链接:https://leetcode-cn.com/problems/calculator-lcci/
给定一个包含正整数、加(+)、减(-)、乘()、除(/)的算数表达式(括号除外),计算其结果。
表达式仅包含非负整数,+, - ,,/ 四种运算符和空格 。 整数除法仅保留整数部分。
例1:
输入: "3+2*2"
输出: 7
例2:
输入: " 3/2 "
输出: 1
例3:
输入: " 3+5 / 2 "
输出: 5
思路:
首先将字符串中得空格去除,然后创建两个栈,分别存储数字(stack_num)和运算符号(stack_oper)
遍历字符串,判断字符是否为数字,为数字则存入stack_num,否则存入satck_oper,当每存入一次数字时,判断stack_oper栈顶是否为‘*/’,如果是stack_num出栈两个数相乘或者相除,将新结果再存入stack_num,
当遍历完全部字符后,再集中处理加减运算符
class Solution(object):
def calculate(self, s):
"""
:type s: str
:rtype: int
"""
s = s.replace(' ','') # 去除空格
stack_num = [] # 创建存储数字的栈
stack_oper = [] # 创建存储运算符号的栈
size = len(s)
num = 0
# 先把乘除符号消除
for i in range(size): # 遍历字符串
if s[i].isdigit(): # 判断第i个字符是否为数字
num = num * 10 + int(s[i]) # 有可能是多位数
if i == size - 1 or not s[i+1].isdigit(): # 判断第i个字符是否位最后一位元素 或者 下一元素不为数字 则执行下一步
stack_num.append(num) # 将数字入栈
num = 0 # 重置
if stack_oper and stack_oper[-1] in {'/', '*'}: # 判断运算栈是否为空 和 栈顶的运算符号是否为 '/*'
oper = stack_oper.pop() # 将运算符号‘/*’移除
n2, n1 = stack_num.pop(), stack_num.pop() # 将放在最上面的两个数字移除出来进行计算
if oper == '*': stack_num.append(n1 * n2) # 将计算结果重新入栈
elif oper == '/': stack_num.append(n1 // n2)
else:
stack_oper.append(s[i]) # 运算符号入栈
# 最后将加减符号消除,计算的时候要从栈底开始计算,其就是按照从左到右的计算逻辑
result = stack_num.pop(0)
while stack_oper:
oper, n = stack_oper.pop(0), stack_num.pop(0)
if oper == '+': result += n
elif oper == '-': result -= n
return result