python中的栈结构_力扣Python描述数据结构之栈实战篇

文章目录前言

1. LeetCode155:最小栈

2. LeetCode1441:用栈操作构建数组

3. LeetCode1021:删除最外层的括号

4. LeetCode682:棒球比赛

5. LeetCode1047:删除字符串中的所有相邻重复项

6. LeetCode496:下一个更大元素 I

7. LeetCode20:有效的括号

前言

LeetCode中有关栈的题目。

1. LeetCode155:最小栈

LeetCode的第155题:最小栈。

这个题基本上就是栈的基本操作,但是题目中明确指出,要设计一个能在常数时间内检索到最小元素的栈。于是乎,直接把元素放在列表里,然后min()操作一下,这样当然不行了,min()操作的时间复杂度也是O ( n ) O(n)O(n)。

既然想到了数组,不如在入栈的时候就开始找最小值,然后把最小值放到一个数组min_list里,入栈完毕后,数组min_list里都是最小值,然后取出即可,这样时间复杂度就是O ( 1 ) O(1)O(1)了。还有一点就是,由于不知道要输入数据量的大小,所以直接用上面博客定义的顺序栈会有栈溢出的风险,所以,这里就不用指针top,而是直接用列表的基本操作来实现顺序栈。

实现代码如下:

class MinStack:

def __init__(self):

"""

initialize your data structure here.

"""

self.S = []

self.min_list = []

def push(self, x):

self.S.append(x)

if len(self.min_list) == 0:

self.min_list.append(x)

else:

self.min_list.append(min(x, self.min_list[-1]))

def pop(self):

self.S.pop()

self.min_list.pop()

def top(self):

return self.S[-1]

def getMin(self):

return self.min_list[-1]

2. LeetCode1441:用栈操作构建数组

LeetCode的第1441题:用栈操作构建数组。

这个题说着是栈,其实只不过是利用了栈的思想。给你一个数组list(大小由n nn决定),利用栈的操作来实现目标数组target,如果数组list中的元素在目标数组target中,则入栈,输出" P u s h " "Push""Push",如果不在,就先入栈然后再出栈,即输出" P u s h " , " P o p " "Push","Pop""Push","Pop",这是大多数情况。还有一个特殊情况就是,如果目标数组target里面的数字是从1开始且连续的,比如t a r g e t = [ 1 , 2 ] , n = 4 target=[1,2],n=4target=[1,2],n=4,则只需要输出" P u s h " , " P u s h " "Push","Push""Push","Push"即可,而不必输出" P u s h " , " P u s h " , " P u s h " , " P o p " , " P u s h " , " P o p " "Push","Push","Push","Pop","Push","Pop""Push","Push","Push","Pop","Push","Pop"。

综上可知,入栈操作的最大次数有目标数组target里面最大的数字决定,代码实现如下:

def buildArray(target, n):

result = []

for num in list(range(1, max(target) + 1)):

if num in target:

result.append('Push')

else:

result.append('Push')

result.append('Pop')

return result

3. LeetCode1021:删除最外层的括号

LeetCode的第1021题:删除最外层的括号。

这个题我没有用栈(数组),大致思路就是用一个flag来表示匹配的括号是否完全闭合,如果完全闭合,则将temp里匹配到的字符放入到result里。代码如下:

def removeOuterParentheses(S):

flag = 0

temp = ''

result = ''

for s in S:

if s == '(':

flag += 1

temp += s

else:

flag -= 1

temp += s

if flag == 0:

result += temp[1:-1]

temp = ''

del flag

del temp

return result

4. LeetCode682:棒球比赛

LeetCode第682题:棒球比赛。

这个题就是遍历一遍就可以了,这里定义一个栈(数组),如果字符是C,则删除栈里面的最后一个;如果字符是D,则将栈里面最后一个数字乘以2再入栈;如果字符是+,则将栈里面最后一个数字和倒数第二个数字相加,然后再入栈;最后将栈里面的所有数字求和,返回结果。代码如下:

def calPoints(ops):

result = []

for s in ops:

if s == 'C':

result.pop()

elif s == 'D':

result.append(2 * result[-1])

elif s == '+':

result.append(result[-1] + result[-2])

else:

result.append(int(s))

return sum(result)

5. LeetCode1047:删除字符串中的所有相邻重复项

LeetCode第1047题:删除字符串中的所有相邻重复项。

这个题应该很快就能想到用栈来解决,大致思路就是,先入栈,如果接下来要入栈的字符与栈里面最后一个字符相同,则这个字符不执行入栈操作,并将栈里面最后一个字符进行出栈操作删除,最后将栈里面的字符转成字符串返回。代码如下:

def removeDuplicates(S):

stack = []

for s1 in S:

if not stack:

stack.append(s1)

else:

if s1 == stack[-1]:

stack.pop()

else:

stack.append(s1)

return ''.join(stack)

6. LeetCode496:下一个更大元素 I

LeetCode第496题:下一个更大元素 I。

这个题的重心要放在nums2上,因为nums1是nums2的一个子集,所以只需要找出nums2每个数字右边的第一个最大值即可,然后用字典存储它们的关系,最后再通过遍历nums1每个数字在字典中对应的值即可。

通过一个栈来找出nums2每个数字右边的第一个最大值,大致思路就是,先判断栈是否为空,如果不为空,说明栈里面的元素还没有找到它右边的第一个最大值;如果后面的数字大于前面的数字,则将栈里面的数字进行出栈操作,直至栈为空,然后再将这个元素入栈;如果后面的数字小于前面的数字,则将其直接入栈。代码如下:

def nextGreaterElement(nums1, nums2):

stack = []

dict1 = {}

result = []

for num in nums2:

# 这个while循环就是找到入栈的元素的右边的第一个最大值

while stack and num > stack[-1]:

dict1[stack[-1]] = num

stack.pop()

stack.append(num)

del stack

for x in nums1:

result.append(dict1.get(x, -1))

return result

7. LeetCode20:有效的括号

LeetCode第20题:有效的括号。

这个题粗略一看感觉和上面第三个题差不多,我也是这样想的,用计数的方式来表示是否匹配,然后就这么提交了。enmmmm,没错,解答错误,因为字符(]这种情况上述的方法就失效了,所以就好好用栈来解决吧。

大致就是,如果是左括号就入栈,是右括号就出栈,如果出栈的括号与匹配的括号是同一种,则继续匹配,否则直接返回False;最后如果栈为空,说明已匹配完毕,返回True,否则就返回False。代码如下:

def isValid(s):

stack = []

for s1 in s:

if s1 == '(' or s1 == '[' or s1 == '{':

stack.append(s1)

else:

try:

if (s1 == ')' and stack.pop() == '(') or (s1 == ']' and stack.pop() == '[') or (s1 == '}' and stack.pop() == '{'):

continue

else:

return False

except Exception as err:

return False

if len(stack) == 0:

return True

else:

return False

上面的代码有些长,现在简化一下,代码如下:

def isValid1(s):

dict1 = {')': '(', ']': '[', '}': '{'}

stack = []

for s1 in s:

if s1 not in dict1:

stack.append(s1)

else:

temp = stack.pop() if stack else None

if temp == dict1.get(s1):

continue

else:

return False

return not stack

对于Python中的not,if操作:None,False,0,空字符串’’,空列表[],空字典{},空元组(),都相当于False,这个小知识点还记得吧。

再次提醒:LeetCode官方给的几个样例都不是白给的,里面有可能包含特殊情况是我没想到的,要多思考,虽然这个题很简单,但是不细心的我在这道题吃了很大的亏(’∇’)シ

文章来源:https://blog.csdn.net/qq_42730750/article/details/107919690

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值