算法训练营day 10- 栈与队列part1

Q1题目链接https://leetcode.com/problems/implement-queue-using-stacks/

leetcode232 用栈实现队列的操作

讲解链接:

. - 力扣(LeetCode)

看到题目的第一思路:

暂无

代码随想录之后的想法和总结:

- 初始化两个栈in和out,出队直接就往in压栈,出队先检查out里面有没有元素,有的话out的栈顶就是队首,否则就先把in里面的元素弹出压入到out中。这样就能保证out的栈顶始终都是队首,in的栈顶始终都是队尾。

- 理解这个解法的关键在于把数据从输入栈倒入输出栈的条件是输出栈为空,这样就维持了输出栈顶是队列开头的定义。

The transfer of elements from stack_in to stack_out ensures that the oldest element added to the queue (which is at the bottom of stack_in) ends up on the top of stack_out. This mimics the behavior of a queue (FIFO - First In, First Out) using two stacks (which are LIFO - Last In, First Out).

遇到的困难:

1 peek函数- peek 函数实际上就是调用了一遍 pop 函数来获取队列的第一个元素,然后将这个元素重新放回队列,以确保队列的状态不变。这样你可以查看队列的第一个元素,而不影响队列本身的内容。

可以记录备用的固定代码方法模版:

class MyQueue:

    def __init__(self):
        #in 负责入栈,out负责出栈
        self.stack_in = []
        self.stack_out = []
        

    def push(self, x: int) -> None:
        #有新元素进来,就往in里面push
        self.stack_in.append(x)
        

    def pop(self) -> int:
        #输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。
        if self.empty():#check if queue is empty
            return None

        if self.stack_out: #Check if stack_out is Non-Empty:不为空的情况下
            return self.stack_out.pop()
        else:
            for i in range (len(self.stack_in)): #如果为空,把所有元素从入栈转移到出栈,并且可以反转元素的顺序,得到我们想要的队列的顺序结果
                self.stack_out.append(self.stack_in.pop())
            return self.stack_out.pop() #弹出并且返回顶部元素
        

    def peek(self) -> int:#调用pop函数来实现获取顶部元素的,但是又把元素重新放回队列以保持队列不变
        #get the front element

        ans = self.pop()
        self.stack_out.append(ans)
        return ans
        

    def empty(self) -> bool:

        return not (self.stack_in or self.stack_out)
        # If both stacks are empty, the expression evaluates to False.
        #not (self.stack_in or self.stack_out) evaluates to True. This indicates that the queue is empty.
        #return True if the queue is empty (i.e., both stack_in and stack_out are empty) and False otherwise.



       

# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

时间复杂度以及空间复杂度:

Time complexity:

  • Push Operation:
    • Time: O(1)
  • Pop Operation:
    • Time: Amortized O(1)
  • Complexity:
  • Best case: O(1), when stack_out is not empty.
  • Worst case: O(n), when stack_out is empty, and we need to transfer all nnn elements from stack_in to stack_out.
  • Amortized Complexity: O(1). Each element is moved between the two stacks at most once, so across multiple operations, the average time per operation is O(1).
  • Peek Operation:
    • Time: Amortized O(1)(similar to pop)
  • Empty Operation:
    • Time: O(1)

Space Complexity: O(n), where n is the number of elements in the queue.


Q2题目链接https://leetcode.com/problems/implement-stack-using-queues/

leetoce 225 用队列实现栈的操作

讲解链接:

代码随想录

看到题目的第一思路:

用两个队列模拟栈

代码随想录之后的想法和总结:

用一个队列实现就够了-将队列除了最后一个元素以外的元素重新添加到队列尾部,此时再去弹出元素就是栈的顺序了

Q:这样输出不是312吗如果是栈不是输出321吗

A:pop是一个一个弹的,312你弹出3,剩下12,如果要再pop就要再进行一次移动,变成21,这下pop就是2了,所以是对的

  • 第一次pop(): 队列deque([1, 2, 3]) -> 移动1到末尾 -> deque([2, 3, 1]) -> 移动2到末尾 -> deque([3, 1, 2]) -> popleft()得到3。栈变为deque([1, 2])

  • 第二次pop(): 队列deque([1, 2]) -> 移动1到末尾 -> deque([2, 1]) -> popleft()得到2。栈变为deque([1])

  • 第三次pop(): 队列deque([1]) -> popleft()得到1。栈变为空deque([])

结论

通过这种方式,每次pop()操作都确保最后进入的元素最先被弹出,即模拟了栈的LIFO行为。因此,虽然底层实现使用了deque(本质上是一个队列结构),但通过特定的操作顺序和方法调用,你成功地模仿了栈的行为。

遇到的困难:

着重看pop和top function: 

  • The top() method uses a similar rotation technique as pop() to access the last element in the deque.
  • Unlike pop(), top() does not remove the last element. Instead, it temporarily stores the last element in a variable (temp), then immediately appends it back to the deque to restore the original order.
  • This way, the top() method returns the top element of the stack without modifying the stack itself.

关于top 和pop的区别:

  • top():

    • Accesses the top element.
    • Does not modify the stack.
    • Useful for inspection and decision-making.
  • pop():

    • Removes and returns the top element.
    • Modifies the stack by removing the top element.
    • Useful for retrieving and processing elements in LIFO order.

可以记录备用的固定代码方法模版:

class MyStack:

    def __init__(self):
        #initialize an empty deque to use as stack
        self.que = deque()
        
    def push(self, x: int) -> None:
        #往队列里放元素模拟栈里放元素
        self.que.append(x)
        

    def pop(self) -> int:
        #check if the queue is empty, then continue
        if self.empty():
            return None
        # self.que.popleft()remove 1 from the front and return it
        # self.que.append() append 1 to back
        #overall, it rotate the element to the end of deque except the last one
        for i in range(len(self.que)-1):
            self.que.append(self.que.popleft())
        #Now, the last element (3, which was the last element before the loop) is at the front.
        #self.que.popleft() removes 3 from the front and returns it. The deque now contains:deque[1,2]
        #So, the pop() method returns 3, which was the top of the stack.
        return self.que.popleft()
        

    def top(self) -> int:
        #check if the queue is empty
        if self.empty():
            return None
        # Rotate elements to the end of the deque except the last one
        for i in range(len(self.que)-1):
            self.que.append(self.que.popleft())
        #self.que.popleft() removes 3 from the front and stores it in temp.
        #self.que.append(temp) appends 3 back to the end of the deque.
        #dequeu now = [1,2,3], temp = 3, return 3
        temp = self.que.popleft()
        self.que.append(temp)
        return temp

    def empty(self) -> bool:
        # Return True if the deque is empty, False otherwise
        return not self.que
        


# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()

时间复杂度以及空间复杂度:

time complexity:

1 push:append an element to deque, O(1)

2 pop: iterate over all element except the last one,takes o(n) time, n is the number of element in the deque

3 top: same as pop

4 empty: check if the deque is empty, takes O(1)

space complexity:

O(1), with additional spaces being O(n) for storing elements in the deque


Q3题目链接https://leetcode.com/problems/valid-parentheses/

leetoce  20 用栈来判断括号是否匹配

讲解链接:

代码随想录

看到题目的第一思路:

题目理解较复杂,应当分类讨论

代码随想录之后的想法和总结:

首先把题目总结为三种类型:

1.左括号多了 2.右括号多了 3.左右括号不匹配例如}{

同理,题目也按三种类型去挨个解决

技巧: 1.遇到左括号存对应的右括号。方便比较。 2.遇到空,就return。 3.剪枝:奇数一定不符合匹配原则。可以直接return

遇到的困难:

暂无

可以记录备用的固定代码方法模版:

class Solution:
    def isValid(self, s: str) -> bool:
        stack = []

        for item in s:
            if item == '(':
                stack.append(')')
            elif item == '[':
                stack.append(']')
            elif item == '{':
                stack.append('}')
            #check if the stack is empty:
            #check if he top of the stack match the current character (closing bracket)
            elif not stack or stack[-1]!= item:
            # The string is not valid (unbalanced or mismatched brackets)
                return False
            else:
                # If the top of the stack matches the current character, pop it from the stack
                stack.pop()
        
        return True if not stack else False
        # Return True if the stack is empty (all brackets matched), otherwise False


        

时间复杂度以及空间复杂度:

time complexity:

Iteration over the string s:

  • The for loop iterates over each character in the string exactly once.
  • The length of the string s is n, so there are n iterations.

operation inside loop- append or pop- O(1)

Overall time complexity: O(n)

space: O(n)

we use of a stack to store the expected closing brackets. In the worst case, the stack could hold all opening brackets if the string consists entirely of unmatched opening brackets (e.g., "(((((").

  • For every opening bracket, a corresponding closing bracket is pushed onto the stack.
  • In the worst case, all characters in the input string could be opening brackets, leading to the stack holding all these brackets. Therefore, the maximum size of the stack is proportional to the length of the input string s.

Q4题目链接https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string/

leetoce 1047 用栈来删除字符串里所有相邻重复元素

讲解链接:

代码随想录

看到题目的第一思路:

和上题类似(上题是遇到相同的括号,做消除动作,这题是遇到相同的相邻字母,做消除动作)

代码随想录之后的想法和总结:

"我们在删除相邻重复项的时候,其实就是要知道当前遍历的这个元素,我们在前一位是不是遍历过一样数值的元素,那么如何记录前面遍历过的元素呢?

所以就是用栈来存放,那么栈的目的,就是存放遍历过的元素,当遍历当前的这个元素的时候,去栈里看一下我们是不是遍历过相同数值的相邻元素。然后再去做对应的消除操作。"来自代码随想录

可以看出来 栈主要是解决相邻元素消除问题,例如消除括号、相同字母,以后类似题目都可以优先用栈解决

遇到的困难:

暂无

可以记录备用的固定代码方法模版:

class Solution:
    def removeDuplicates(self, s: str) -> str:
        # Initialize an empty list to use as a stack
        res = list()

        # Iterate through each character in the input string s
        for item in s:
        # If the stack is not empty and the top of the stack (last item in the list)
        # is the same as the current character, remove the top of the stack
            if res and res[-1] == item:
                res.pop()
            else:
            # Otherwise, push the current character onto the stack
                res.append(item)

    # Join the characters in the stack to form the resulting string without duplicates
        return "".join(res)
        

时间复杂度以及空间复杂度:

  • Time Complexity: O(n), because the function iterates through the string once, performing constant-time operations for each character.
  • The function iterates over each character in the string exactly once. Therefore, the iteration takes O(n) time.
  • For each character, the code performs either a push or a pop operation on the stack,both push and pop operations on a list (acting as a stack) are O(1) operations.
  • Space Complexity: O(n), due to the use of a stack that may, in the worst case, store all characters of the input string.

In the worst case, if there are no duplicate characters in the input string, all characters will be added to the stack. This means the stack could potentially hold all n characters, leading to O(n) space usage.


今日收获,学习时长:

12h

刷题不易,还需坚持

初步对栈和队列的实际应用产生了理解,继续加油

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值