栈+单调栈解法
前言
本博客总结了一些与栈相关的leetcode题目,记录一下,时常复习。
一、栈是什么?
栈遵循:先进后出原则。
二、Leetcode题目
1.Leetcode155-最小栈
题目:
设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
- push(x) – 将元素 x 推入栈中。
- pop() – 删除栈顶的元素。
- top() – 获取栈顶元素。
- getMin() – 检索栈中的最小元素
class MinStack(object):
def __init__(self):
self.stack = [] # 存放所有元素
self.minStack = [] # 存放每一次压入数据时,栈中的最小值
def push(self, x):
self.stack.append(x)
if not self.minStack or self.minStack[-1] >= x:
self.minStack.append(x)
def pop(self): # 移除栈顶元素时,判断是否移除栈中最小值
if self.minStack[-1] == self.stack[-1]:
del self.minStack[-1]
self.stack.pop()
def top(self):
return self.stack[-1]
def getMin(self):
return self.minStack[-1]
2.Leetcode20-有效的括号
题目:
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
class Solution:
def isValid(self, s):
mapping = {")": "(", "]": "[", "}": "{"}
stack = []
for i, char in enumerate(s):
if char not in mapping: # left
stack.append(char)
else:
if not stack or stack[-1] != mapping[char]:
return False
stack.pop()
return len(stack) == 0
三、单调栈Leetcode相关题目
单调栈即栈内的数据严格单调递增或者严格单调递减。
3.1 Leetcode739-每日温度
题目:
根据每日气温列表,请重新生成一个列表,对应位置的输入是你需要再等待多久温度才会升高的天数。如果之后都不会升高,请输入0来代替。
- 例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
- 你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
class Solution(object):
def dailyTemperatures(self, T):
ans = [0] * len(T)
stack = []
for i, t in enumerate(T):
while stack and T[stack[-1]] < t:
prev_idx = stack.pop()
ans[prev_idx] = i - prev_idx
stack.append(i)
return ans
3.2 Leetcode496-下一个最大元素I
题目:
给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。
# 暴力查找
class Solution(object):
def nextGreaterElement(self, nums1, nums2):
if not nums1 or not nums2:
return []
ans = []
for item in nums1:
index = nums2.index(item)
for i in range(index, len(nums2)):
if nums2[i] > item:
ans.append(nums2[i])
break
if i + 1 == len(nums2) and nums2[-1] <= item:
ans.append(-1)
return ans
# 用栈
class Solution(object):
def nextGreaterElement(self, nums1, nums2):
mapping = dict()
stack = []
# 遍历nums2中的所有元素,找到比下个元素大的数存入mapping中,采用哈希表的思想
for num in nums2:
while stack and stack[-1] < num:
top = stack.pop()
mapping[top] = num
stack.append(num)
# 遍历nums1中的元素,看看是否在mapping中出现,若有输出,否则输出-1
ans = []
for num in nums1:
if num in mapping:
ans.append(mapping[num])
else:
ans.append(-1)
return ans
3.3 Leetcode503-下一个最大元素II
题目:
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。
数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,
这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
-----------------------------------------------------------------------------------
示例:
输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
class Solution:
def nextGreaterElements(self, nums):
length = len(nums)
ans = [-1 for i in range(length)]
stack = []
# 列表的拼接构成循环队列
double = nums + nums
for idx, num in enumerate(double):
while stack and nums[stack[-1]] < num:
ans[stack[-1]] = num
stack.pop()
if idx < length:
stack.append(idx)
return ans
3.4 Leetcode1019-链表中的下一个更大节点
题目:
给出一个以头节点 head 作为第一个节点的链表。链表中的节点分别编号为:node_1, node_2, node_3, …
每个节点都可能有下一个更大值(next larger value):
对于 node_i,如果其 next_larger(node_i) 是 node_j.val,那么就有 j > i 且 node_j.val> node_i.val
而 j 是可能的选项中最小的那个。如果不存在这样的 j ,那么下一个更大值为 0 。
返回整数答案数组 answer,其中 answer[i] = next_larger(node_{i+1}) 。
-----------------------------------------------------------------------------------------------
示例1:
输入:[2,1,5]
输出:[5,5,0]
示例2:
输入:[2,7,4,3,5]
输出:[7,0,5,5,0]
class Solution(object):
def nextLargerNodes(self, head):
"""
:type head: ListNode
:rtype: List[int]
"""
h = head
L = list()
#把链表转数组
while(h):
L.append(h.val)
h = h.next
stack = list()
ans = [0 for i in range(len(L))]
cnt = 0
while(cnt < (len(L))):
if not stack or L[stack[-1]] >= L[cnt]:
stack.append(cnt)
else:
while(stack and L[stack[-1]] < L[cnt]):
ans[stack[-1]] = L[cnt]
stack.pop()
stack.append(cnt)
cnt += 1
return ans
总结
对单调栈的解题思路有了充分的理解,加油,刷题崽!