动手刷力扣第四天——栈与队列(力扣933,20,496)

文章详细介绍了栈和队列两种数据结构,包括它们的基本概念、操作(如插入、删除、搜索)以及在Python中的实现。文中通过力扣的两道题目——有效括号和下一个更大元素——展示了栈在括号匹配问题中的应用,以及队列在寻找最近求和次数问题中的使用。此外,还分析了这些操作的时间复杂度和空间复杂度。
摘要由CSDN通过智能技术生成

栈是限制仅在表的一端(表尾)进行操作(插入和删除)的线性表,是一种后进先出(Last in First Out)的数据结构,简称 LIFO。表尾又叫栈顶(Top),允许插入和删除,那么另一端就叫做栈底(Bottom),啥也不能干,只能干等着第一个进栈的过来躺着。栈的插入操作,叫做入栈(push)。存入栈的元素之间没有任何具体的关系,只有到来的时间的先后顺序。栈的删除操作,叫做出栈(pop)。

下面我们讨论一下栈的访问,搜索,插入,删除等操作。

栈的访问,插入与删除(栈顶):

由于后进先出原则,栈的访问,插入与删除偶是对栈顶元素进行的,时间复杂度为O(1)

栈的搜索:

栈的搜索要从栈顶元素开始,一直找到我们要搜索的元素N为止,时间复杂度为O(N)

下面是python中常用的栈的操作:

# create an stack
stack = []
 
# add element    time complexity:O(1)
stack.append(1)
stack.append(2)
stack.append(3)
print(stack)    # [1,2,3]
 
# get the top of stack    time complexity:O(1)
stack[-1]    
 
 
# remove  the top of stack    time complexity:O(1)
temp = stack.pop
print(temp)    # 3
 
 
# get size
size = len(stack)
print(size)    # 2

# Iterate stack    time complexity:O(N)
while len(stack) > 0:
    temp = stack.pop()
    print(temp)

熟悉了栈的相关操作后我们来看看对应的简单题。力扣20有效的括号:

 对于这道题,我们首先定义一个栈用来存放左扩号,在遍历字符串的过程中,遇到左括号就将其存进栈中,若遇到右括号,则将之与栈中的左括号进行匹配,若匹配失败则返回false,重复直到全部遍历完成,若都匹配成功了则返回True。

    def isValid(self, s: str):
        if len(s) == 0:
            return True
        stack = []                  # 定义一个栈
        for c in s:
            if c == '(' or c == '[' or c == '{':    # 遍历整个字符串,如果是左括号,放到栈里去
                stack.append(c)
            else:                                   # 如果是右括号,
                if len(stack) == 0:         # 栈里面为空,就没有对应的左括号返回false
                    return False
                else:                       # 不为空
                    temp = stack.pop()      # 定义一个临时变量把栈里的左括号拿出来看看匹不匹配
                    if c == ')'and temp != '(':
                        return False
                    if c == ']' and temp != '[':
                        return False
                    if c == '}' and temp != '{':
                        return False
        if len(stack) == 0:   # 都匹配了,遍历完了,就证明符合,匹配的右括号
            return True
        else:                 # 如果栈里还有,证明有左括号没有与之匹配的右括号,返回false
            return False
# 时间复杂度:O(N)
# 空间复杂度:O(N)

再来看一下力扣496下一个更大元素:

 对于这道题,首先定义一个RES数组来存储下一个更大的元素,定义一个栈存放num2,再对num1进行遍历,依次去对比num1中元素和栈中元素的大小,找出下一个更大元素,返回给RES数组,同时temp用于临时存放栈中元素以便还原。

class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]):
        RES = []
        stack = []
        for num in nums2:
            stack.append(num)       # 把num2放进栈里
        for i in nums1:
            temp = []               # 定义临时变量存储栈出来的元素以便恢复原来的栈
            found = False           # 定义布尔值决定循环是否继续
            max = -1                # 比x大的值初始赋值-1
            while(len(stack ) != 0 and found == False):    
                top = stack.pop()   # 依次取出值
                if top > i:         # 大于num1里的值,先赋值给max
                    max = top
                elif top == i:       # 等于num1里的值,证明找到这个元素了(唯一),结束循环
                    found = True
                temp.append(top)    # 把取出来的放在temp里面,等一下再放回去恢复栈的原样
            RES.append(max)
            while(len(temp) != 0):
                stack.append(temp.pop()) # 把temp里的值依次放回stack里面
        return RES
# time complexity: O(MN) 分别遍历了两个数组
# space complexity: O(N) num2存放在shack里面

队列是限制仅在一端进行插入操作,在另一端进行删除操作的线性表。是一种先进先出(First in First Out)的数据结构,简称 FIFO。允许删除的一端叫做队头,允许插入的一端叫做队尾。队列的插入叫做入队,队列的删除叫做出队

下面我们讨论一下栈的访问,搜索,插入,删除等操作。

队列的访问与搜索:

由于先进先出原则,队列的访问与搜索都需要遍历队列直到找到要找的元素,时间复杂度为O(N)

队列的插入与删除:

同样由于先进先出原则,队列的插入与删除可以直接在头和尾进行,时间复杂度为O(1)

下面是python中常用的队列的操作:

# create a queue
queue = deque()
 
# add element    time complexity:O(1)
queue.append(1)
queue.append(2)
queue.append(3)
print(queue)    # [1,2,3]
 
# get the head of queue    time complexity:O(1)
temp1 = queue[0]
print(temp1)    # 1   
 
 
# remove the head of queue    time complexity:O(1)
temp2 = queue.popleft()
print(temp2)    # 1
print(queue)    # [2,3]
 
 
# get size
size = len(queue)
print(size)    # 2

# Iterate stack    time complexity:O(N)
while len(queue) != 0:
    temp = queue.popleft()
    print(temp)

熟悉了队列的相关操作后我们来看看对应的简单题。力扣933最近的求和次数:

 对于这道题,我们定义一个队列q,把时间t挨个加进来,取t-3000(即保证两次请求在3000毫秒内)的值超过就出列,返回队列长度即可。

class RecentCounter:

    def __init__(self):
        self.q = deque()

    def ping(self, t: int) -> int:
        self.q.append(t)                            # 挨个加入队列
        while(self.q[0] < t - 3000):                # 保证队列内的请求范围在3000ms内
            self.q.popleft()                        # 把第一个元素删掉即出队
        return len(self.q)                          # 返回队列长度即在0-3000ms内的请求次数

# time complexity:O(N)     while循环把t全部添加了一次
# space complexity:O(N)    产生了一个队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值