Hello! In our previous lesson, we explored the stack and its Last-In, First-Out (LIFO) principle, which is essential for handling nested structures and reversal logic. You learned how to implement a stack efficiently in Python using collections.deque and applied it to solve the "Valid Parentheses" problem.
Today, we shift our focus to the stack's counterpart: the queue. We will dive into its First-In, First-Out (FIFO) principle, a fundamental concept for managing tasks, requests, or data in the order they are received. You'll see this pattern is at the heart of many systems you've likely worked with as a full-stack developer, from message brokers to background job processors. By the end of this lesson, you will be able to implement a queue in Python and apply it to solve a classic interview problem that requires FIFO processing.
What is a Queue? The FIFO Principle
A queue is a linear data structure that, unlike a stack, follows the First-In, First-Out (FIFO) rule. This means the first element added to the queue will be the first one to be removed. Think of it as a line of people waiting for a service: the person who arrived first is the first one served.
This "first-come, first-served" behavior is crucial in many computing scenarios. For example, a web server handling incoming requests, a printer managing a queue of print jobs, or a system processing events in a specific sequence all rely on FIFO logic.
The video below from the codebasics channel provides an excellent real-world analogy involving producer-consumer systems, which should be very familiar from your backend development experience.
Queue - Data Structures & Algorithms Tutorials In Python #8
This video introduces the queue data structure using a practical example of a stock price feed.
Watch the first part of the video, from the beginning to the FIFO explanation. Pay close attention to how a queue can decouple producers (like the NYSE) from consumers (like Yahoo Finance), creating a more robust and scalable architecture. This is a powerful system design pattern.
The core operations of a queue reflect this behavior:
- Enqueue: Adds an element to the rear (or back) of the queue.
- Dequeue: Removes and returns the element from the front of the queue.
- Front (or Peek): Returns the front element without removing it.
- is_empty: Checks if the queue is empty.
- size: Returns the number of elements in the queue.

Just like stacks, these core operations are designed to be highly efficient, ideally running in constant time, .
Implementing a Queue in Python
As with stacks, Python offers several ways to implement a queue. Your ability to discuss the trade-offs between these methods is a key point in technical interviews.
The list approach (and why it's inefficient)
You can use a Python list to simulate a queue. You would use list.append() to enqueue an item and list.pop(0) to dequeue an item.
my_queue = []
my_queue.append('a') # enqueue
my_queue.append('b') # enqueue
print(my_queue.pop(0)) # dequeue 'a'
However, this is highly inefficient. While append() is an amortized operation, pop(0) is an operation because removing an element from the beginning of a list requires shifting all subsequent elements one position to the left. For a large queue, this is unacceptably slow.
The collections.deque approach (the right way)
The collections.deque object (pronounced "deck," for double-ended queue) is the correct tool for the job. As you saw in the last lesson, it's built on a doubly-linked list, which provides fast appends and pops from both ends.
To implement a queue with a deque, you use:
deque.append()to enqueue (add to the right end).deque.popleft()to dequeue (remove from the left end).
Both of these operations are guaranteed to have time complexity.
The following article from Real Python provides an excellent, in-depth guide to using deque for queues.
Python's deque: Implement Efficient Queues and Stacks
This article explains precisely why deque is the preferred tool for implementing queues in Python and shows you how to build a custom Queue class around it.
Please read the section "Build Efficient Queues With deque". Focus on the example of a custom Queue class that wraps a deque. This is a great pattern that combines the efficiency of deque with the clean, encapsulated interface of a class, which is something you'd appreciate in production code.
As a summary of the implementation, the image below shows a complete Python Queue class, its methods, and a visual representation of how a queue object is structured in memory.
Problem-Solving with Queues: Number of Recent Calls
Now, let's tackle a LeetCode problem that perfectly demonstrates the utility of a queue's FIFO nature: Number of Recent Calls (LeetCode 933).
The Problem: You have a RecentCounter class that counts the number of recent requests within a certain time frame. It has one method:
ping(t): Adds a new request at timet(in milliseconds) and returns the number of requests that have happened in the past 3000 milliseconds (i.e., in the inclusive range[t - 3000, t]).
You are guaranteed that every call to ping will use a strictly larger value of t than the previous call.
Thinking Through the Solution:
The core of this problem is maintaining a "sliding window" of time. We only care about requests that fall within the [t - 3000, t] range.
- When a new ping arrives at time
t, we need to record it. - We also need to discard any old pings that are now outside the new time window. For a new ping at time
t, any recorded ping with a timestamp less thant - 3000is no longer relevant. - The number of pings remaining is our answer.
Since timestamps t are always increasing, once a ping becomes too old, it will never be recent again. This means we can discard old pings in the same order they arrived. This "add to one end, remove from the other" logic is a perfect fit for a queue.
The algorithm is:
- Initialize an empty queue (using
collections.deque) to store the timestamps of the pings. - For each
ping(t)call:
a. Add the new timestamptto the rear of the queue (enqueue).
b. While the queue is not empty and the timestamp at the front of thequeue is less thant - 3000, remove it from the front (dequeue).
c. The current size of the queue is the number of recent calls. Return this size.
This video provides a very clear walkthrough of this exact logic and its implementation.
Number of Recent Calls - LeetCode 933 #leetcode #leetcode75
This video from Deepti Talesra clearly explains the solution to the "Number of Recent Calls" problem using a queue.
First, watch the problem explanation to understand the requirements and examples. Next, see how a queue is used to solve the problem conceptually from this segment. The key insight here is that you only need to keep track of relevant pings within the time window. Then, follow the Python implementation, which uses collections.deque exactly as we discussed. Finally, the analysis of time and space complexity is an important part of any interview solution.
The beauty of this solution is its efficiency. Because each timestamp is enqueued once and dequeued at most once, the work done for each ping call is amortized constant time.
Conclusion
In this lesson, we moved from the LIFO world of stacks to the FIFO world of queues. You've seen how this simple, fair-minded data structure is the backbone of many ordered processing systems.
Key Takeaways:
- A queue is a linear data structure that operates on a First-In, First-Out (FIFO) principle.
- The primary operations are Enqueue (add to back) and Dequeue (remove from front), which should have an time complexity.
- In Python,
collections.dequeis the ideal tool for implementing a queue, usingappend()for enqueue andpopleft()for dequeue. Using alistwithpop(0)is inefficient. - Queues are the natural choice for problems involving ordered processing, task scheduling, or managing a sliding window of recent items, as seen in the "Number of Recent Calls" problem.
In our next lesson, we will revisit stacks to explore a more advanced technique: the monotonic stack. You'll learn how this specialized variant can be used to efficiently solve problems like "Next Greater Element," which are common challenges in coding interviews.