Skip to content

Deque (Double-Ended Queue)

A deque (double-ended queue) is a linear data structure that allows insertion and deletion of elements from both ends (front and rear). It combines the functionality of both stacks and queues, providing maximum flexibility for element access patterns.

Features

  • Dual-ended access - Insert and remove from both front and rear in O(1) time
  • Stack and queue hybrid - Can function as both LIFO and FIFO data structure
  • Efficient operations - O(1) for all basic operations at both ends
  • Dynamic size - automatically grows and shrinks as needed
  • Memory efficient - uses doubly linked list for optimal memory usage
  • Type safe - generic implementation with type checking
  • Iterator support - can iterate in both directions (forward and reverse)
  • Utility operations - search, count, rotate, reverse, and copy functionality

Time Complexities

Operation Time Complexity Description
Add Front O(1) Insert element at front
Add Rear O(1) Insert element at rear
Remove Front O(1) Remove element from front
Remove Rear O(1) Remove element from rear
Front O(1) View front element
Rear O(1) View rear element
Search O(n) Find element position
Count O(n) Count occurrences
Clear O(1) Remove all elements
Copy O(n) Create shallow copy
Reverse O(n) Reverse deque order
Rotate O(k) Rotate by k positions
Size/Length O(1) Get number of elements

Space Complexity: O(n) where n is the number of elements

Basic Usage

Creating and Initializing

from algo.data_structs.stacks_queues.deque import Deque

# Create empty deque
deque = Deque()

# Check if empty
print(deque.is_empty())    # True
print(len(deque))          # 0
print(deque.size())        # 0

# Create with initial elements
deque = Deque([1, 2, 3, 4, 5])
print(len(deque))          # 5
print(deque.to_list())     # [1, 2, 3, 4, 5]

# Deque is generic - can specify type
int_deque = Deque[int]()
str_deque = Deque[str]()

Adding Elements

# Add to rear (right side)
deque = Deque()
deque.add_rear(1)
deque.add_rear(2)
deque.add_rear(3)

print(deque.to_list())     # [1, 2, 3]
print(deque.front())       # 1
print(deque.rear())        # 3

# Add to front (left side)
deque.add_front(0)
deque.add_front(-1)

print(deque.to_list())     # [-1, 0, 1, 2, 3]
print(deque.front())       # -1
print(deque.rear())        # 3

# Using convenience aliases
deque.append(4)            # Same as add_rear
deque.appendleft(-2)       # Same as add_front

print(deque.to_list())     # [-2, -1, 0, 1, 2, 3, 4]

Viewing Elements

# Peek at both ends without removing
front_element = deque.front()
rear_element = deque.rear()

print(f"Front: {front_element}")  # -2
print(f"Rear: {rear_element}")    # 4
print(len(deque))                 # Still same size

# Check if deque contains element
print(1 in deque)          # True
print(99 in deque)         # False

# Convert to list (front to rear order)
elements = deque.to_list()
print(elements)            # [-2, -1, 0, 1, 2, 3, 4]

Removing Elements

# Remove from front
front_removed = deque.remove_front()
print(front_removed)       # -2
print(deque.front())       # -1

# Remove from rear
rear_removed = deque.remove_rear()
print(rear_removed)        # 4
print(deque.rear())        # 3

# Using convenience aliases
left_removed = deque.popleft()   # Same as remove_front
right_removed = deque.pop()      # Same as remove_rear

print(left_removed)        # -1
print(right_removed)       # 3
print(deque.to_list())     # [0, 1, 2]

Clearing the Deque

# Add some elements
deque.extend([5, 6, 7, 8, 9])
print(len(deque))          # 8

# Clear all elements
deque.clear()
print(len(deque))          # 0
print(deque.is_empty())    # True

Advanced Operations

Extending with Iterables

deque = Deque()

# Extend to rear (normal order)
deque.extend([1, 2, 3])
print(deque.to_list())     # [1, 2, 3]

# Extend to front (reversed order)
deque.extendleft([4, 5])
# Elements added one by one: first 4, then 5
print(deque.to_list())     # [5, 4, 1, 2, 3]

# Extend with different iterables
deque.extend((6, 7))       # Tuple
deque.extendleft("ab")     # String (characters)
print(deque.to_list())     # ['b', 'a', 5, 4, 1, 2, 3, 6, 7]

Rotation Operations

deque = Deque([1, 2, 3, 4, 5])
print(f"Original: {deque.to_list()}")

# Rotate right (positive steps)
deque.rotate(2)
print(f"Rotate right 2: {deque.to_list()}")  # [4, 5, 1, 2, 3]

# Rotate left (negative steps)
deque.rotate(-1)
print(f"Rotate left 1: {deque.to_list()}")   # [5, 1, 2, 3, 4]

# Full rotation (same as original)
deque.rotate(5)  # Rotate by length
print(f"Full rotation: {deque.to_list()}")   # [5, 1, 2, 3, 4] (unchanged)

Reversing the Deque

deque = Deque([1, 2, 3, 4, 5])
print(f"Original: {deque.to_list()}")

# Reverse in place
deque.reverse()
print(f"Reversed: {deque.to_list()}")        # [5, 4, 3, 2, 1]
print(f"Front: {deque.front()}")             # 5
print(f"Rear: {deque.rear()}")               # 1

Search and Count Operations

Finding Elements

deque = Deque([1, 2, 3, 2, 4, 2])

# Search returns position from front (0-based)
print(deque.search(1))     # 0 (front element)
print(deque.search(2))     # 1 (first occurrence of 2)
print(deque.search(3))     # 2 (third position from front)
print(deque.search(4))     # 4 (fifth position from front)
print(deque.search(99))    # -1 (not found)

# Check membership
print(2 in deque)          # True
print(99 in deque)         # False

Counting Elements

# Count occurrences of elements
print(deque.count(2))      # 3 (appears 3 times)
print(deque.count(1))      # 1 (appears once)
print(deque.count(99))     # 0 (not present)

# Count all elements
total_elements = len(deque)
print(total_elements)      # 6

Iteration and Traversal

deque = Deque(['apple', 'banana', 'cherry', 'date'])

# Iterate from front to rear
print("Deque contents (front to rear):")
for item in deque:
    print(item)  # apple, banana, cherry, date

# Convert to list for processing
items = list(deque)
print(items)               # ['apple', 'banana', 'cherry', 'date']

# Reverse iteration (rear to front)
print("Deque contents (rear to front):")
for item in deque.reversed_iter():
    print(item)  # date, cherry, banana, apple

# Enumerate with position
for i, item in enumerate(deque):
    print(f"Position {i}: {item}")

Working with Different Types

String Elements

words = Deque()
words.append("hello")
words.append("world")
words.appendleft("python")

print(words.front())       # "python"
print(words.rear())        # "world"
print("world" in words)    # True
print(words.count("hello")) # 1

Numeric Elements

numbers = Deque([1, 2, 3, 4, 5])
numbers.append(3.14)
numbers.appendleft(42)

print(numbers.front())     # 42
print(numbers.rear())      # 3.14
print(3.14 in numbers)     # True
print(len(numbers))        # 7

Mixed Types

mixed = Deque()
mixed.append("string")
mixed.append(42)
mixed.appendleft([1, 2, 3])   # Lists can be stored
mixed.appendleft(True)

print(mixed.front())       # True
print(mixed.rear())        # 42
print(42 in mixed)         # True
print(len(mixed))          # 4

Custom Objects

class Task:
    def __init__(self, name: str, priority: int):
        self.name = name
        self.priority = priority

    def __eq__(self, other):
        return isinstance(other, Task) and self.name == other.name

    def __str__(self):
        return f"Task({self.name}, priority={self.priority})"

tasks = Deque()
task1 = Task("Write code", 1)
task2 = Task("Test code", 2)
task3 = Task("Deploy", 3)

tasks.append(task1)
tasks.append(task2)
tasks.appendleft(task3)

print(tasks.front())       # Task(Deploy, priority=3)
print(tasks.rear())        # Task(Test code, priority=2)
print(task1 in tasks)      # True
print(len(tasks))          # 3

Deque Manipulation

Copying Deques

original = Deque([1, 2, 3, 4, 5])

# Create a copy
copy_deque = original.copy()

# Verify they have same contents
print(copy_deque.to_list() == original.to_list())  # True
print(len(copy_deque) == len(original))             # True

# Verify they're independent
original.append(6)
print(len(original))       # 6
print(len(copy_deque))     # 5 (unchanged)

copy_deque.appendleft(99)
print(99 in original)      # False
print(99 in copy_deque)    # True

String Representation

# Empty deque
empty_deque = Deque()
print(str(empty_deque))    # Deque([])

# Non-empty deque
deque = Deque([1, 2, 3])
print(str(deque))          # Deque([1 <-> 2 <-> 3])

# Detailed representation for debugging
print(repr(deque))         # Deque(size=3, front=1, rear=3)

Error Handling

deque = Deque()

# Safe operations on empty deque
print(deque.is_empty())    # True
print(len(deque))          # 0
print(deque.search(42))    # -1
print(deque.count(42))     # 0
print(42 in deque)         # False

# Operations that raise errors on empty deque
try:
    deque.remove_front()
except IndexError as e:
    print(f"Error: {e}")   # Error: Cannot remove from empty deque

try:
    deque.remove_rear()
except IndexError as e:
    print(f"Error: {e}")   # Error: Cannot peek rear of empty deque

try:
    deque.front()
except IndexError as e:
    print(f"Error: {e}")   # Error: Cannot peek front of empty deque

try:
    deque.rear()
except IndexError as e:
    print(f"Error: {e}")   # Error: Cannot peek rear of empty deque

# Alias methods also raise appropriate errors
try:
    deque.pop()
except IndexError as e:
    print(f"Error: {e}")   # Error: Cannot remove from empty deque

try:
    deque.popleft()
except IndexError as e:
    print(f"Error: {e}")   # Error: Cannot remove from empty deque

Common Patterns

Using as Stack (LIFO)

# Stack behavior using rear end
stack = Deque()

# Push elements (to rear)
stack.append(1)
stack.append(2)
stack.append(3)
print(f"Stack: {stack.to_list()}")  # [1, 2, 3]

# Pop elements (from rear) - LIFO order
while not stack.is_empty():
    item = stack.pop()
    print(f"Popped: {item}")  # 3, 2, 1

Using as Queue (FIFO)

# Queue behavior using both ends
queue = Deque()

# Enqueue elements (to rear)
queue.append(1)
queue.append(2)
queue.append(3)
print(f"Queue: {queue.to_list()}")  # [1, 2, 3]

# Dequeue elements (from front) - FIFO order
while not queue.is_empty():
    item = queue.popleft()
    print(f"Dequeued: {item}")  # 1, 2, 3

Sliding Window Operations

def sliding_window_example():
    """Example of sliding window using deque rotation."""
    data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    window_size = 3

    window = Deque()
    results = []

    # Process each element
    for i, value in enumerate(data):
        window.append(value)

        # Maintain window size
        if len(window) > window_size:
            window.popleft()

        # Process complete windows
        if len(window) == window_size:
            window_sum = sum(window.to_list())
            results.append(window_sum)
            print(f"Window {list(window.to_list())}: sum = {window_sum}")

    return results

sliding_window_example()
# Output shows sum of each sliding window of size 3

Buffer Management

class CircularBuffer:
    def __init__(self, capacity: int):
        self.capacity = capacity
        self.deque = Deque()

    def add(self, item):
        """Add item to buffer, removing oldest if at capacity."""
        if len(self.deque) >= self.capacity:
            removed = self.deque.popleft()
            print(f"Buffer full, removed: {removed}")

        self.deque.append(item)
        print(f"Added: {item}, buffer: {self.deque.to_list()}")

    def get_all(self):
        """Get all items in buffer order."""
        return self.deque.to_list()

# Usage
buffer = CircularBuffer(capacity=3)
for i in range(6):
    buffer.add(f"item_{i}")

print(f"Final buffer: {buffer.get_all()}")

Practical Applications

Palindrome Checker

from algo.data_structs.stacks_queues.deque import is_palindrome

# Test palindrome checking
test_strings = [
    "racecar",
    "hello", 
    "A man a plan a canal Panama",
    "race a car",
    "Madam",
    "12321",
    "12345"
]

for text in test_strings:
    result = is_palindrome(text)
    print(f"'{text}' is palindrome: {result}")

# Custom palindrome checker showing deque operations
def check_palindrome_manual(text: str) -> bool:
    """Manual palindrome check showing deque operations."""
    deque = Deque()

    # Add only alphanumeric characters (lowercase)
    for char in text.lower():
        if char.isalnum():
            deque.append(char)

    print(f"Cleaned text in deque: {deque.to_list()}")

    # Compare from both ends
    while len(deque) > 1:
        front_char = deque.popleft()
        rear_char = deque.pop()
        print(f"Comparing '{front_char}' and '{rear_char}'")

        if front_char != rear_char:
            return False

    return True

print("\nManual palindrome check:")
result = check_palindrome_manual("A man a plan a canal Panama")
print(f"Result: {result}")

Sliding Window Maximum

from algo.data_structs.stacks_queues.deque import sliding_window_maximum

# Find maximum in sliding windows
arrays = [
    ([1, 3, -1, -3, 5, 3, 6, 7], 3),
    ([1, 1, 1, 1, 1], 2),
    ([9, 8, 7, 6, 5, 4, 3, 2, 1], 3),
    ([1, 2, 3, 4, 5], 1),
]

for arr, k in arrays:
    result = sliding_window_maximum(arr, k)
    print(f"Array: {arr}")
    print(f"Window size: {k}")
    print(f"Sliding maximums: {result}")
    print()

# Manual implementation showing deque usage
def sliding_max_manual(arr, k):
    """Manual sliding window maximum showing deque operations."""
    if not arr or k <= 0:
        return []

    indices_deque = Deque()  # Store indices of useful elements
    result = []

    for i, num in enumerate(arr):
        print(f"\nProcessing element {num} at index {i}")

        # Remove indices outside current window
        while not indices_deque.is_empty() and indices_deque.front() <= i - k:
            removed_idx = indices_deque.popleft()
            print(f"  Removed index {removed_idx} (outside window)")

        # Remove indices with smaller values (they can't be maximum)
        while not indices_deque.is_empty() and arr[indices_deque.rear()] <= num:
            removed_idx = indices_deque.pop()
            print(f"  Removed index {removed_idx} (smaller value {arr[removed_idx]})")

        indices_deque.append(i)
        print(f"  Added index {i}")
        print(f"  Deque indices: {indices_deque.to_list()}")

        # Add result when we have a complete window
        if i >= k - 1:
            max_idx = indices_deque.front()
            max_val = arr[max_idx]
            result.append(max_val)
            print(f"  Window [{i-k+1}:{i+1}] maximum: {max_val}")

    return result

print("Manual sliding window maximum:")
test_arr = [1, 3, -1, -3, 5, 3, 6, 7]
manual_result = sliding_max_manual(test_arr, 3)
print(f"Final result: {manual_result}")

Undo/Redo System

class UndoRedoSystem:
    def __init__(self, max_history: int = 10):
        self.max_history = max_history
        self.history = Deque()
        self.current_state = None

    def execute_action(self, action: str, state):
        """Execute an action and save state for undo."""
        if self.current_state is not None:
            # Save current state to history
            self.history.append((action, self.current_state))

            # Limit history size
            if len(self.history) > self.max_history:
                self.history.popleft()

        self.current_state = state
        print(f"Executed: {action} -> {state}")

    def undo(self):
        """Undo the last action."""
        if not self.history.is_empty():
            action, previous_state = self.history.pop()
            print(f"Undoing: {action}")
            self.current_state = previous_state
            return previous_state
        else:
            print("Nothing to undo")
            return None

    def can_undo(self) -> bool:
        """Check if undo is possible."""
        return not self.history.is_empty()

    def get_history(self):
        """Get current history."""
        return [action for action, _ in self.history.to_list()]

# Usage
editor = UndoRedoSystem(max_history=5)

editor.execute_action("type 'Hello'", "Hello")
editor.execute_action("type ' World'", "Hello World")
editor.execute_action("delete 6 chars", "Hello")
editor.execute_action("type ' Python'", "Hello Python")

print(f"Current state: {editor.current_state}")
print(f"History: {editor.get_history()}")

# Undo operations
while editor.can_undo():
    state = editor.undo()
    print(f"State after undo: {state}")

Task Scheduler with Priority

class PriorityTaskScheduler:
    def __init__(self):
        self.high_priority = Deque()
        self.normal_priority = Deque()
        self.low_priority = Deque()

    def add_task(self, task: str, priority: str = "normal"):
        """Add task with specified priority."""
        if priority == "high":
            self.high_priority.append(task)
        elif priority == "low":
            self.low_priority.append(task)
        else:
            self.normal_priority.append(task)

        print(f"Added {priority} priority task: {task}")

    def add_urgent_task(self, task: str):
        """Add urgent task to front of high priority queue."""
        self.high_priority.appendleft(task)
        print(f"Added URGENT task to front: {task}")

    def process_next_task(self):
        """Process next task based on priority."""
        # Check high priority first
        if not self.high_priority.is_empty():
            task = self.high_priority.popleft()
            print(f"Processing HIGH priority: {task}")
            return task

        # Then normal priority
        if not self.normal_priority.is_empty():
            task = self.normal_priority.popleft()
            print(f"Processing NORMAL priority: {task}")
            return task

        # Finally low priority
        if not self.low_priority.is_empty():
            task = self.low_priority.popleft()
            print(f"Processing LOW priority: {task}")
            return task

        print("No tasks to process")
        return None

    def show_status(self):
        """Show current task queues."""
        print(f"High priority tasks: {self.high_priority.to_list()}")
        print(f"Normal priority tasks: {self.normal_priority.to_list()}")
        print(f"Low priority tasks: {self.low_priority.to_list()}")

# Usage
scheduler = PriorityTaskScheduler()

# Add various tasks
scheduler.add_task("Send email", "normal")
scheduler.add_task("Backup database", "low")
scheduler.add_task("Fix critical bug", "high")
scheduler.add_task("Update documentation", "normal")
scheduler.add_urgent_task("Server is down!")

scheduler.show_status()

# Process all tasks
print("\nProcessing tasks:")
while True:
    task = scheduler.process_next_task()
    if task is None:
        break

Web Browser History

class BrowserHistory:
    def __init__(self, max_history: int = 50):
        self.max_history = max_history
        self.history = Deque()
        self.current_page = None

    def visit(self, url: str):
        """Visit a new page."""
        if self.current_page:
            self.history.append(self.current_page)

            # Limit history size
            if len(self.history) > self.max_history:
                self.history.popleft()

        self.current_page = url
        print(f"Visited: {url}")

    def back(self):
        """Go back to previous page."""
        if not self.history.is_empty():
            previous = self.history.pop()
            self.current_page = previous
            print(f"Back to: {previous}")
            return previous
        else:
            print("No previous page")
            return None

    def forward_to_recent(self):
        """Go to most recent page in history."""
        if not self.history.is_empty():
            recent = self.history.pop()
            if self.current_page:
                self.history.append(self.current_page)
            self.current_page = recent
            print(f"Forward to: {recent}")
            return recent
        return None

    def get_recent_history(self, count: int = 5):
        """Get recent history."""
        history_list = self.history.to_list()
        return history_list[-count:] if len(history_list) >= count else history_list

# Usage
browser = BrowserHistory(max_history=10)

# Simulate browsing
pages = [
    "google.com",
    "github.com", 
    "stackoverflow.com",
    "python.org",
    "docs.python.org",
    "realpython.com"
]

for page in pages:
    browser.visit(page)

print(f"Current page: {browser.current_page}")
print(f"Recent history: {browser.get_recent_history(3)}")

# Navigate back
browser.back()
browser.back()
print(f"After going back: {browser.current_page}")

Use Cases

When to Use Deques

Good for:

  • Sliding window algorithms
  • Implementing both stacks and queues
  • Palindrome checking
  • Undo/redo functionality
  • Browser history management
  • Task scheduling with priorities
  • Circular buffers
  • Breadth-first search with backtracking
  • Dynamic programming with space optimization

Examples:

# Sliding window maximum
sliding_deque = Deque()
sliding_deque.append(window_element)

# Stack and queue combined
dual_ended = Deque()
dual_ended.append(item)      # Add to rear
dual_ended.appendleft(item)  # Add to front
dual_ended.pop()             # Remove from rear
dual_ended.popleft()         # Remove from front

# Palindrome checking
palindrome_deque = Deque()
palindrome_deque.extend(text)

# Undo/redo system
history_deque = Deque()
history_deque.append(action)

When NOT to Use Deques

Avoid for:

  • Random access to middle elements (use arrays/lists)
  • Frequent searches in large datasets (use hash tables)
  • Sorted data operations (use heaps or balanced trees)
  • Simple single-ended operations (use specialized stack/queue)

Better alternatives:

# For random access, use list
random_access = [1, 2, 3, 4, 5]
print(random_access[2])  # Direct access to index 2

# For sorted operations, use heapq
import heapq
priority_queue = []
heapq.heappush(priority_queue, (priority, item))

# For fast searches, use set or dict
fast_lookup = {1, 2, 3, 4, 5}
print(3 in fast_lookup)  # O(1) lookup

# For simple stack, use list
simple_stack = []
simple_stack.append(item)  # Push
simple_stack.pop()         # Pop

Performance Characteristics

Time Complexity Analysis

  • Front/Rear operations: O(1) - constant time for both ends
  • Search operations: O(n) - linear time traversal
  • Rotation: O(k) where k is rotation steps
  • Memory allocation: O(1) per element (doubly linked list)
  • Space overhead: Moderate (two pointers per node)

Memory Efficiency

# Deque uses doubly linked list internally
# Memory per element: data + two pointers (next, prev)
# No pre-allocation of fixed arrays
# Memory grows/shrinks dynamically

deque = Deque()
print(f"Empty deque memory efficient: {deque.is_empty()}")

# Memory usage scales linearly with elements
for i in range(1000):
    deque.append(i)
# Only allocates memory for actual elements

Comparison with Other Data Structures

Operation Deque List Stack Queue Array
Add Front O(1) O(n) N/A N/A O(n)
Add Rear O(1) O(1) O(1) O(1) O(1)*
Remove Front O(1) O(n) N/A O(1) O(n)
Remove Rear O(1) O(1) O(1) N/A O(1)
Random Access O(n) O(1) O(n) O(n) O(1)
Memory Overhead Medium Low Low Low Low
Use Case Both Ends Random Access LIFO FIFO Indexed

*Array add rear may require reallocation

Advanced Features

Rotation Patterns

# Demonstrate rotation for different use cases
def rotation_examples():
    # Circular shift for encryption
    message = Deque(list("HELLO"))
    print(f"Original: {''.join(message.to_list())}")

    message.rotate(3)  # Caesar cipher shift
    print(f"Shifted: {''.join(message.to_list())}")

    # Round-robin scheduling
    processes = Deque(["P1", "P2", "P3", "P4"])
    print("\nRound-robin scheduling:")

    for time_slice in range(8):
        current = processes.front()
        print(f"Time {time_slice}: Running {current}")
        processes.rotate(1)  # Next process

rotation_examples()

Custom Iteration

def custom_iteration_examples():
    deque = Deque([1, 2, 3, 4, 5])

    # Forward iteration
    print("Forward:", [x for x in deque])

    # Reverse iteration
    print("Reverse:", [x for x in deque.reversed_iter()])

    # Custom iteration patterns
    def zigzag_iter(dq):
        """Iterate alternating from front and rear."""
        temp_deque = dq.copy()
        from_front = True

        while not temp_deque.is_empty():
            if from_front:
                yield temp_deque.popleft()
            else:
                yield temp_deque.pop()
            from_front = not from_front

    print("Zigzag:", list(zigzag_iter(deque)))

custom_iteration_examples()

API Reference

Deque (Double-Ended Queue) Implementation

A deque is a double-ended queue that allows insertion and deletion at both ends. It's a generalization of both stacks and queues, providing efficient operations at both the front and rear.

Key Features:

  • Add/remove elements at both front and rear in O(1) time
  • Can be used as both stack and queue
  • Supports iteration in both directions
  • Dynamic size allocation

Common Use Cases:

  • Sliding window problems
  • Palindrome checking
  • Implementing undo/redo functionality
  • Browser history management
  • A* search algorithm (maintaining open/closed lists)

Time Complexities:

  • Add/remove front: O(1)
  • Add/remove rear: O(1)
  • Access front/rear: O(1)
  • Size: O(1)
  • Search: O(n)

Space Complexity: O(n)

Deque(iterable=None)

Bases: Generic[T]

A deque implementation using a doubly linked list as the underlying data structure.

This implementation provides efficient O(1) operations at both ends by maintaining references to both head and tail of the doubly linked list.

Initialize a deque.

Parameters:

Name Type Description Default
iterable Optional[Iterable[T]]

Optional iterable to initialize the deque with. Elements are added in order from front to rear.

None

__contains__(value)

Check if a value exists in the deque.

__iter__()

Return an iterator over the deque elements from front to rear.

__len__()

Return the number of elements in the deque.

__repr__()

Return detailed string representation for debugging.

__str__()

Return string representation of the deque.

add_front(element)

Add an element to the front of the deque.

Time Complexity: O(1)

Parameters:

Name Type Description Default
element T

Element to add to the front

required

add_rear(element)

Add an element to the rear of the deque.

Time Complexity: O(1)

Parameters:

Name Type Description Default
element T

Element to add to the rear

required

append(element)

Alias for add_rear - add element to the rear.

appendleft(element)

Alias for add_front - add element to the front.

clear()

Remove all elements from the deque.

Time Complexity: O(1)

copy()

Create a shallow copy of the deque.

Time Complexity: O(n)

Returns:

Type Description
Deque[T]

A new Deque with the same elements

count(target)

Count the number of occurrences of an item in the deque.

Time Complexity: O(n)

Parameters:

Name Type Description Default
target T

Item to count

required

Returns:

Type Description
int

Number of occurrences

extend(iterable)

Add all elements from an iterable to the rear of the deque.

Time Complexity: O(k) where k is the number of elements

Parameters:

Name Type Description Default
iterable

Iterable containing elements to add

required

extendleft(iterable)

Add all elements from an iterable to the front of the deque.

Time Complexity: O(k) where k is the number of elements

Parameters:

Name Type Description Default
iterable

Iterable containing elements to add

required
Note

Elements are added one by one to the front, so the final order will be reversed compared to the original iterable.

front()

Return the front element without removing it.

Time Complexity: O(1)

Returns:

Type Description
T

The front element of the deque

Raises:

Type Description
IndexError

If the deque is empty

is_empty()

Check if the deque is empty.

Time Complexity: O(1)

Returns:

Type Description
bool

True if the deque is empty, False otherwise

pop()

Alias for remove_rear - remove element from the rear.

popleft()

Alias for remove_front - remove element from the front.

rear()

Return the rear element without removing it.

Time Complexity: O(1)

Returns:

Type Description
T

The rear element of the deque

Raises:

Type Description
IndexError

If the deque is empty

remove_front()

Remove and return the front element from the deque.

Time Complexity: O(1)

Returns:

Type Description
T

The front element of the deque

Raises:

Type Description
IndexError

If the deque is empty

remove_rear()

Remove and return the rear element from the deque.

Time Complexity: O(1)

Returns:

Type Description
T

The rear element of the deque

Raises:

Type Description
IndexError

If the deque is empty

reverse()

Reverse the deque in place.

Time Complexity: O(n)

Note

After reversal, the front element becomes the rear element.

reversed_iter()

Return an iterator over the deque elements from rear to front.

Returns:

Type Description
Iterator[T]

Iterator that goes from rear to front

rotate(steps=1)

Rotate the deque n steps to the right.

Time Complexity: O(min(steps, n)) where n is the size

Parameters:

Name Type Description Default
steps int

Number of steps to rotate right (negative for left rotation)

1
Note

Positive steps rotate right (rear elements move to front) Negative steps rotate left (front elements move to rear)

search(target)

Search for an item in the deque and return its position from the front.

Time Complexity: O(n)

Parameters:

Name Type Description Default
target T

Item to search for

required

Returns:

Type Description
int

Position from front (0-based), or -1 if not found

size()

Get the number of elements in the deque.

Time Complexity: O(1)

Returns:

Type Description
int

The number of elements in the deque

to_list()

Convert the deque to a Python list.

Time Complexity: O(n)

Returns:

Type Description
list[T]

A Python list with elements from front to rear

is_palindrome(text)

Check if a string is a palindrome using deque.

Time Complexity: O(n) Space Complexity: O(n)

Parameters:

Name Type Description Default
text str

String to check

required

Returns:

Type Description
bool

True if string is a palindrome, False otherwise

sliding_window_maximum(array, window_size)

Find maximum in each sliding window of size k using deque.

Time Complexity: O(n) Space Complexity: O(k)

Parameters:

Name Type Description Default
array list[int]

Input array

required
window_size int

Window size

required

Returns:

Type Description
list[int]

List of maximum values in each window