1.0155. 最小栈
1.1 题目大意
要求:设计一个「栈」。实现 push
,pop
,top
,getMin
操作,其中 getMin
要求能在常数时间内实现。
说明:
- −231≤𝑣𝑎𝑙≤231−1。
pop
、top
和getMin
操作总是在非空栈上调用push
,pop
,top
和getMin
最多被调用 3∗104 次。
运行:
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
self.stack_=[]
self.min_stack=[]
def push(self, x):
self.stack_.append(x)
if(len(self.min_stack)==0):
self.min_stack.append(x)
elif(x<=self.min_stack[-1]):
self.min_stack.append(x)
def pop(self):
if self.stack_[-1]==self.min_stack[-1]:
self.min_stack.pop()
self.stack_.pop()
def top(self):
return self.stack_[-1]
def getMin(self):
return self.min_stack[-1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
2.0020. 有效的括号
2.1 题目大意
描述:给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
。
要求:判断字符串 s
是否有效(即括号是否匹配)。
说明:
- 有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
运行:
class Solution:
def isValid(self, s):
"""
:type s: str
:rtype: bool
"""
stack=[] #设置一个列表,把该列表当做栈来使用即可。
dic={')':'(','}':'{',']':'['} #使用字典存储括号,并且右括号为key,左括号为value
for char in s:
if char in dic.values(): #左括号就入栈
stack.append(char)
elif char in dic.keys(): #有右括号的话就进行比较,
if stack==[] or dic[char] != stack.pop():
return False
else:
return False #不再字典中的输入直接输出错误
return stack==[] #如果栈最后是空的,那么则符合要求,输出true,如果不是,则输出false,使用一个条件表达式
3.0227. 基本计算器 II
3.1 题目大意
描述:给定一个字符串表达式 s
,表达式中所有整数为非负整数,运算符只有 +
、-
、*
、/
,没有括号。
要求:实现一个基本计算器来计算并返回它的值。
说明:
- 1≤𝑠.𝑙𝑒𝑛𝑔𝑡ℎ≤3∗105。
s
由整数和算符(+
、-
、*
、/
)组成,中间由一些空格隔开。s
表示一个有效表达式。- 表达式中的所有整数都是非负整数,且在范围 [0,231−1] 内。
- 题目数据保证答案是一个 32-bit 整数。
示例:
输入:s = "3+2*2"
输出:7
输入:s = " 3/2 "
输出:1
运行:
class Solution(object):
def calculate(self, s):
"""
:type s: str
:rtype: int
"""
s = s.replace(" ", "")
stack = []
operation = []
i = 0
while i < len(s): #分离数字和运算符
if s[i].isdigit():
cur = int(s[i])
while i + 1 < len(s) and s[i + 1].isdigit():
cur = cur * 10 + int(s[i + 1])
i += 1
stack.append(cur)
else:
operation.append(s[i])
i += 1
print stack, operation
i = 0
while i < len(operation): #处理乘除法
op = operation[i]
if op == "*":
stack[i] = stack[i] * stack[i + 1]
stack = stack[:i + 1] + stack[i + 2:]
operation = operation[:i] + operation[i + 1:]
elif op == "/":
stack[i] = stack[i] // stack[i + 1]
stack = stack[:i + 1] + stack[i + 2:]
operation = operation[:i] + operation[i + 1:]
else:
i += 1
# print stack, operation
res = stack[0]
for i in range(len(operation)): #计算加减法
op = operation[i]
if op == "+":
res += stack[i + 1]
elif op == "-":
res -= stack[i + 1]
return res
1.0150. 逆波兰表达式求值
1.1 题目大意
描述:给定一个字符串数组 tokens
,表示「逆波兰表达式」。
要求:求解表达式的值。
说明:
-
逆波兰表达式:也称为后缀表达式。
- 中缀表达式
( 1 + 2 ) * ( 3 + 4 )
,对应的逆波兰表达式为( ( 1 2 + ) ( 3 4 + ) * )
。
- 中缀表达式
- 1≤𝑡𝑜𝑘𝑒𝑛𝑠.𝑙𝑒𝑛𝑔𝑡ℎ≤104。
-
tokens[i]
是一个算符(+
、-
、*
或/
),或是在范围 [−200,200] 内的一个整数。
示例:
输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]
输出:22
解释:该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
运行:
class Solution(object):
def evalRPN(self, tokens):
"""
:type tokens: List[str]
:rtype: int
"""
# 逆波兰表达式:是一种后缀表达式,所谓后缀就是指算符写在后面。
# 两个优点 1 去掉括号后无歧义 2 适合栈运算
stack = []
for i in tokens:
if tokens and i not in {"+", "-", "*", "/"}:
stack.append(i)
else:
x = stack.pop()
y = stack.pop()
if i == "+":
temp = int(y) + int(x)
elif i == "-":
temp = int(y) - int(x)
elif i == "*":
temp = int(y) * int(x)
# python的 b / a 会向下取整, 比如 -1 / 132 = -1。
#题目要求是取整数部分,那么负数的时候,实际应该是向上取整, 解决方法: (b / float(a))
elif i == "/":
temp = (int(y) / float(x))
stack.append(temp)
return int(stack.pop())
2.0394. 字符串解码
2.1 题目大意
描述:给定一个经过编码的字符串 s
。
要求:返回 s
经过解码之后的字符串。
说明:
- 编码规则:
k[encoded_string]
。encoded_string
为字符串,k
为整数。表示字符串encoded_string
重复k
次。 - 1≤𝑠.𝑙𝑒𝑛𝑔𝑡ℎ≤30。
s
由小写英文字母、数字和方括号[]
组成。s
保证是一个有效的输入。s
中所有整数的取值范围为 [1,300]。
示例:
输入:s = "3[a]2[bc]"
输出:"aaabcbc"
输入:s = "3[a2[c]]"
输出:"accaccacc"
运行:
class Solution:
def decodeString(self, s):
res, stack, tmp_cnt = '', [], 0
for c in s:
if c == '[': # 遇到 [ 进栈
stack.append((tmp_cnt, res))
tmp_cnt, res = 0, '' # 重置为0和空,重新开始进入下一个 []
elif c == ']': # 出栈的情况
cnt, last_res = stack.pop()
res = last_res + cnt * res
elif '0' <= c <= '9': # 处理数字部分
tmp_cnt = tmp_cnt * 10 + int(c)
else:
res += c
return res
3.0946. 验证栈序列
3.1 题目大意
描述:给定两个整数序列 pushed
和 popped
,每个序列中的值都不重复。
要求:如果第一个序列为空栈的压入顺序,而第二个序列 popped
为该栈的压出序列,则返回 True
,否则返回 False
。
说明:
- 1≤𝑝𝑢𝑠ℎ𝑒𝑑.𝑙𝑒𝑛𝑔𝑡ℎ≤1000。
- 0≤𝑝𝑢𝑠ℎ𝑒𝑑[𝑖]≤1000。
- 𝑝𝑢𝑠ℎ𝑒𝑑 的所有元素互不相同。
- 𝑝𝑜𝑝𝑝𝑒𝑑.𝑙𝑒𝑛𝑔𝑡ℎ==𝑝𝑢𝑠ℎ𝑒𝑑.𝑙𝑒𝑛𝑔𝑡ℎ。
- 𝑝𝑜𝑝𝑝𝑒𝑑 是 𝑝𝑢𝑠ℎ𝑒𝑑 的一个排列。
示例:
输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1
输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出:false
解释:1 不能在 2 之前弹出。
运行:
class Solution:
def validateStackSequences(self, pushed, popped):
# 利用栈来模拟入栈和出栈操作
stack = []
# index 表示 popped 数组中元素的下标
# 比如 popped 是 [4,5,3,2,1]
# 那么第 0 个下标元素是 4 这个数字
# 先去判断这个数字能否正常的出栈
index = 0
# 遍历 pushed 数组中的每个元素
for item in pushed:
# 在遍历 pushed 数组时,把当前遍历的元素加入到栈中
stack.append(item)
# 加入完之后,不断的执行以下的判断
# 1、栈中是否有元素
# 2、栈顶元素是否和 popped 当前下标的元素相同
# 如果同时满足这两个条件
# 说明这个元素可以满足要求,即可以在最初空栈上进行推入 push 和弹出 pop 操作
while stack and stack[-1] == popped[index] :
# 那么就把栈顶元素弹出
stack.pop()
# 同时 index++,观察 popped 下一个元素
index += 1
return len(stack) ==0
1.0496. 下一个更大元素 I
1.1 题目大意
描述:给定两个没有重复元素的数组 nums1
和 nums2
,其中 nums1
是 nums2
的子集。
要求:找出 nums1
中每个元素在 nums2
中的下一个比其大的值。
说明:
nums1
中数字x
的下一个更大元素是指:x
在nums2
中对应位置的右边的第一个比x
大的元素。如果不存在,对应位置输出-1
。- 1≤𝑛𝑢𝑚𝑠1.𝑙𝑒𝑛𝑔𝑡ℎ≤𝑛𝑢𝑚𝑠2.𝑙𝑒𝑛𝑔𝑡ℎ≤1000。
- 0≤𝑛𝑢𝑚𝑠1[𝑖],𝑛𝑢𝑚𝑠2[𝑖]≤104。
- 𝑛𝑢𝑚𝑠1 和 𝑛𝑢𝑚𝑠2 中所有整数互不相同。
- 𝑛𝑢𝑚𝑠1 中的所有整数同样出现在 𝑛𝑢𝑚𝑠2 中。
运行:
class Solution(object):
def nextGreaterElement(self, nums1, nums2):
# 生成下一个更大元素对应哈希表
hashmap = {}
stack = []
for num in nums2:
while stack:
if stack[-1] < num:
hashmap[stack.pop(-1)] = num
else:
break
stack.append(num)
for num in stack:
hashmap[num] = -1
# 返回结果
return [hashmap[num] for num in nums1]
2.0739. 每日温度
2.1 题目大意
描述:给定一个列表 temperatures
,temperatures[i]
表示第 i
天的气温。
要求:输出一个列表,列表上每个位置代表「如果要观测到更高的气温,至少需要等待的天数」。如果之后的气温不再升高,则用 0
来代替。
说明:
- 1≤𝑡𝑒𝑚𝑝𝑒𝑟𝑎𝑡𝑢𝑟𝑒𝑠.𝑙𝑒𝑛𝑔𝑡ℎ≤105。
- 30≤𝑡𝑒𝑚𝑝𝑒𝑟𝑎𝑡𝑢𝑟𝑒𝑠[𝑖]≤100。
示例:
输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]
输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]
运行:
class Solution:
def dailyTemperatures(self, temperatures):
sta=[]
ret=[0]*len(temperatures)
i=0
for t in temperatures:
while len(sta)>0 and i >0:
if t >temperatures[sta[-1]]:
n=sta.pop()
ret[n]=i-n
else:
break
sta.append(i)
i+=1
return ret
3.0316. 去除重复字母
3.1 题目大意
描述:给定一个字符串 s
。
要求:去除字符串中重复的字母,使得每个字母只出现一次。需要保证 「返回结果的字典序最小(要求不能打乱其他字符的相对位置)」。
说明:
- 1≤𝑠.𝑙𝑒𝑛𝑔𝑡ℎ≤104。
s
由小写英文字母组成。
示例:
输入:s = "bcabc"
输出:"abc"
输入:s = "cbacdcbc"
输出:"acdb"
运行:
class Solution(object):
def removeDuplicateLetters(self, s):
if not s:
return ""
count = Counter(s)
pos = 0
for i in range(len(s)):
if s[i] < s[pos]:
pos = i
count[s[i]] -= 1
if count[s[i]] == 0:
break
return s[pos] + self.removeDuplicateLetters(s[pos:].replace(s[pos], ""))