代码随想录算法训练营第十天| 232.用栈实现队列、 225. 用队列实现栈

在Python中,栈和队列可以使用列表(List)来实现,因为列表提供了在末尾进行添加append()和弹出pop()操作的高效方法。然而,这里有一些需要注意的事项:

  • 栈的实现
    栈是一种后进先出(Last In, First Out,LIFO)的数据结构。在Python中,可以使用列表的 append() 方法来在末尾添加元素,使用pop()方法从末尾移除元素。Python中的列表可以方便地用作栈。
    虽然在许多情况下,使用列表作为栈是非常方便的,但在某些需要高效的情况下,例如在频繁插入和删除操作的大型数据集合中,可能需要考虑使用 collections 模块中的 deque 类,它提供了 O(1) 复杂度的队列和栈操作。
  • 队列的实现
    表(List): 你可以使用列表的 append() 方法在队尾添加元素,使用 pop(0) 方法在队头删除元素。然而,在列表的开头执行 pop(0)操作会导致所有后续元素的移动,因此可能不是最高效的方法,特别是对于大型队列。如果队列很大,而且频繁地在队头执行删除操作,可能需要考虑使用其他数据结构。
    collections 模块中的 deque: collections 模块提供了 deque 类,它是一个双端队列的实现。deque 支持高效的队列操作,包括在两端进行元素的添加和删除。你可以使用 append()popleft() 方法在队尾添加元素和在队头删除元素,它们的时间复杂度均为 O(1)。因此,对于大型队列和需要频繁操作队头的情况,使用 deque 可能更合适。
    queue 模块中的 Queue: Python 的标准库中提供了 queue 模块,其中的 Queue 类是一个线程安全的队列实现。它支持多线程环境下的安全操作,提供了 put()get() 方法用于入队和出队操作。Queue 类的实现基于 deque。
    综上所述,对于一般情况下的队列操作,可以使用列表或者 collections 模块中的 deque。如果需要在多线程环境下操作队列,可以考虑使用 queue 模块中的 Queue 类。

232.用栈实现队列 - 🔗

讲解 - 🔗
💡刚开始没什么思路,后来看了一下文字解析稍微能自己写了。做题的时候发现list.pop()方法是有返回值的,返回被移除的元素的值,并且原始列表被修改,移除了指定位置的元素。所以通常会有list.append(list.pop())这种写法。可以直接将pop()的返回值作为参数传递给list.append()

class MyQueue:

   def __init__(self):
       self.stack_in = []
       self.stack_out = []

   def push(self, x: int) -> None:
       self.stack_in.append(x)

   def pop(self) -> int:
       if self.stack_out:
           return self.stack_out.pop()
       else:
           for i in range(len(self.stack_in)):
               self.stack_out.append(self.stack_in.pop()) #list.pop()会返回被pop的值
           return self.stack_out.pop()

   def peek(self) -> int:
       tmp = self.pop()
       self.stack_out.append(tmp)
       return tmp

   def empty(self) -> bool:
       if self.stack_in or self.stack_out:
           return False
       else:
           return True
           
# 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()

最后一部分⬇️可以改写为return not (self.stack_in or self.stack_out)

def empty(self) -> bool:
	if self.stack_in or self.stack_out:
		return False
	else:
		return True

225. 用队列实现栈 - 🔗

讲解 - 🔗
💡在之前还不是特别明白这道题的意思的时候,我一直觉得这道题很简单,因为我想着直接用一个deque,不就可以同时实现先入先出和先入后出了吗?但是我没有考虑到是要用队列实现栈。也就是说deque只能使用append+popleft功能或者appendleft+pop功能,才能符合队列的先入先出。

方法一:一个deque
from collections import deque

class MyStack:
   # 把deque当成一个单向列表,由于遵循先入先出原则
   # 只能同时拥有append + popleft,或者append + pop
   def __init__(self):
       self.queue = deque()

   def push(self, x: int) -> None:
       self.queue.append(x)

   def pop(self) -> int:
       if self.empty():
           return None
       # 固定最后一个元素,将前面的所有元素按先入先出的顺序popleft再append到最后一个元素后面
       # 于是最后一个元素就变成了第一个元素
       for i in range(len(self.queue) - 1):
           self.queue.append(self.queue.popleft())
       return self.queue.popleft()

   def top(self) -> int:
       if self.empty():
           return None
       for i in range(len(self.queue) - 1):
           self.queue.append(self.queue.popleft())
       tmp = self.queue.popleft()
       self.queue.append(tmp)
       return tmp

   def empty(self) -> bool:
       if self.queue:
           return False
       else:
           return True
方法二:两个deque - 不同于用栈实现队列,另一个deque是用于备份的
from collections import deque

class MyStack:
    # 把deque当成一个单向列表,由于遵循先入先出原则,只能同时拥有append + popleft,或者append + pop
    def __init__(self):
        self.queue = deque()
        self.backup = deque()

    def push(self, x: int) -> None:
        self.queue.append(x)

    def pop(self) -> int:
        if self.empty():
            return None
        # 将先放入的元素移到backup备份
        for i in range(len(self.queue) - 1):
            self.backup.append(self.queue.popleft())
        # 获取到要移出的元素
        tmp  = self.queue.popleft()
        # 将备份里的元素按原有顺序重新放到队列里
        for i in range(len(self.backup)):
            self.queue.append(self.backup.popleft())
        return tmp

    def top(self) -> int:
        if self.empty():
            return None
        # 将先放入的元素移到backup备份
        for i in range(len(self.queue) - 1):
            self.backup.append(self.queue.popleft())
        # 获取到top元素
        tmp  = self.queue.popleft()
        # 将备份里的元素按原有顺序重新放到队列里
        for i in range(len(self.backup)):
            self.queue.append(self.backup.popleft())
        self.queue.append(tmp)
        return tmp

    def empty(self) -> bool:
        if self.queue:
            return False
        else:
            return True
  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,使得子数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值