Table of Contents
- Introduction
- Stack Fundamentals
- Implementation Methods
- Operations and Time Complexity
- Practical Applications
- Common Problems
- Advanced Topics
Introduction
A Stack is a linear data structure that follows the Last-In-First-Out (LIFO) principle. The last element added to the stack will be the first one to be removed. Think of it like a stack of plates – you can only add or remove plates from the top.
Real-World Analogies
- Stack of plates in a cafeteria
- Browser back button (navigation history)
- Undo mechanism in text editors
- Call stack in programming
Key Characteristics
- LIFO: Last In, First Out
- Restricted Access: Elements can only be added or removed from one end (top)
- Dynamic Size: Can grow or shrink as needed
Stack Fundamentals
Basic Operations
- Push: Add an element to the top of the stack
- Pop: Remove and return the top element
- Peek/Top: View the top element without removing it
- isEmpty: Check if the stack is empty
- Size: Get the number of elements in the stack
Visual Representation
Initial Stack: After Push(5): After Pop():
| | | | | |
| 3 | ← Top | 5 | ← Top | 3 | ← Top
| 2 | | 3 | | 2 |
| 1 | | 2 | | 1 |
----- | 1 | -----
-----PythonImplementation Methods
Method 1: Using Python List
Python lists provide built-in methods that make stack implementation straightforward.
class Stack:
"""Stack implementation using Python list"""
def __init__(self):
"""Initialize an empty stack"""
self.items = []
def is_empty(self):
"""Check if stack is empty"""
return len(self.items) == 0
def push(self, item):
"""Add an item to the top of stack"""
self.items.append(item)
def pop(self):
"""Remove and return the top item"""
if self.is_empty():
raise IndexError("pop from empty stack")
return self.items.pop()
def peek(self):
"""Return the top item without removing it"""
if self.is_empty():
raise IndexError("peek from empty stack")
return self.items[-1]
def size(self):
"""Return the number of items in stack"""
return len(self.items)
def __str__(self):
"""String representation of stack"""
return f"Stack({self.items})"
def __repr__(self):
return self.__str__()
# Example usage
stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)
print(f"Stack: {stack}") # Stack([1, 2, 3])
print(f"Top element: {stack.peek()}") # 3
print(f"Popped: {stack.pop()}") # 3
print(f"Size: {stack.size()}") # 2
print(f"Is empty: {stack.is_empty()}") # FalsePythonMethod 2: Using collections.deque
The deque (double-ended queue) is more efficient for stack operations than a list.
from collections import deque
class StackDeque:
"""Stack implementation using collections.deque"""
def __init__(self):
self.items = deque()
def is_empty(self):
return len(self.items) == 0
def push(self, item):
self.items.append(item)
def pop(self):
if self.is_empty():
raise IndexError("pop from empty stack")
return self.items.pop()
def peek(self):
if self.is_empty():
raise IndexError("peek from empty stack")
return self.items[-1]
def size(self):
return len(self.items)
def __str__(self):
return f"Stack({list(self.items)})"
# Example usage
stack = StackDeque()
stack.push(10)
stack.push(20)
stack.push(30)
print(stack) # Stack([10, 20, 30])PythonMethod 3: Using Linked List
A linked list implementation provides O(1) operations and dynamic memory allocation.
class Node:
"""Node for linked list"""
def __init__(self, data):
self.data = data
self.next = None
class StackLinkedList:
"""Stack implementation using Linked List"""
def __init__(self):
self.top = None
self._size = 0
def is_empty(self):
return self.top is None
def push(self, item):
"""Add item to top of stack"""
new_node = Node(item)
new_node.next = self.top
self.top = new_node
self._size += 1
def pop(self):
"""Remove and return top item"""
if self.is_empty():
raise IndexError("pop from empty stack")
popped_data = self.top.data
self.top = self.top.next
self._size -= 1
return popped_data
def peek(self):
"""Return top item without removing"""
if self.is_empty():
raise IndexError("peek from empty stack")
return self.top.data
def size(self):
return self._size
def __str__(self):
"""String representation (top to bottom)"""
items = []
current = self.top
while current:
items.append(current.data)
current = current.next
return f"Stack({items})"
# Example usage
stack = StackLinkedList()
stack.push('A')
stack.push('B')
stack.push('C')
print(stack) # Stack(['C', 'B', 'A'])
print(stack.pop()) # CPythonMethod 4: Using queue.LifoQueue (Thread-safe)
For multi-threaded applications, use the thread-safe LifoQueue.
from queue import LifoQueue
# Create a stack with maximum size
stack = LifoQueue(maxsize=5)
# Push items
stack.put(1)
stack.put(2)
stack.put(3)
# Pop items
print(stack.get()) # 3
print(stack.get()) # 2
# Check if empty
print(stack.empty()) # False
# Check if full
print(stack.full()) # False
# Get size
print(stack.qsize()) # 1PythonOperations and Time Complexity
Time Complexity Analysis
| Operation | List | Deque | Linked List | LifoQueue |
|---|---|---|---|---|
| Push | O(1)* | O(1) | O(1) | O(1) |
| Pop | O(1) | O(1) | O(1) | O(1) |
| Peek | O(1) | O(1) | O(1) | N/A |
| isEmpty | O(1) | O(1) | O(1) | O(1) |
| Size | O(1) | O(1) | O(1) | O(1) |
*Amortized O(1) – occasionally O(n) when list needs to resize
Space Complexity
- All implementations: O(n) where n is the number of elements
Comparison of Implementation Methods
import time
from collections import deque
def benchmark_stack_operations(n=100000):
"""Compare performance of different stack implementations"""
# List-based stack
start = time.time()
list_stack = []
for i in range(n):
list_stack.append(i)
for i in range(n):
list_stack.pop()
list_time = time.time() - start
# Deque-based stack
start = time.time()
deque_stack = deque()
for i in range(n):
deque_stack.append(i)
for i in range(n):
deque_stack.pop()
deque_time = time.time() - start
print(f"List-based: {list_time:.4f} seconds")
print(f"Deque-based: {deque_time:.4f} seconds")
print(f"Deque is {list_time/deque_time:.2f}x faster")
# Run benchmark
benchmark_stack_operations()PythonPractical Applications
1. Balanced Parentheses Checker
Check if parentheses, brackets, and braces are balanced in an expression.
def is_balanced(expression):
"""
Check if parentheses are balanced
Examples:
is_balanced("()[]{}") → True
is_balanced("([)]") → False
is_balanced("{[()]}") → True
"""
stack = []
opening = "([{"
closing = ")]}"
pairs = {"(": ")", "[": "]", "{": "}"}
for char in expression:
if char in opening:
stack.append(char)
elif char in closing:
if not stack:
return False
if pairs[stack.pop()] != char:
return False
return len(stack) == 0
# Test cases
test_cases = [
"()[]{}",
"([)]",
"{[()]}",
"(((",
"())",
"{[(])}",
""
]
for expr in test_cases:
print(f"{expr:15} → {is_balanced(expr)}")PythonOutput:
()[]{} → True
([)] → False
{[()]} → True
((( → False
()) → False
{[(])} → False
→ TruePython2. Reverse a String
def reverse_string(s):
"""Reverse a string using stack"""
stack = []
# Push all characters to stack
for char in s:
stack.append(char)
# Pop all characters to build reversed string
reversed_str = ""
while stack:
reversed_str += stack.pop()
return reversed_str
# Alternative: Pythonic one-liner
def reverse_string_pythonic(s):
return s[::-1]
# Test
text = "Hello, World!"
print(f"Original: {text}")
print(f"Reversed: {reverse_string(text)}")Python3. Infix to Postfix Conversion
Convert mathematical expressions from infix to postfix notation.
def infix_to_postfix(expression):
"""
Convert infix expression to postfix
Example: "A+B*C" → "ABC*+"
"""
precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3}
stack = []
output = []
for char in expression:
# Operand
if char.isalnum():
output.append(char)
# Left parenthesis
elif char == '(':
stack.append(char)
# Right parenthesis
elif char == ')':
while stack and stack[-1] != '(':
output.append(stack.pop())
stack.pop() # Remove '('
# Operator
else:
while (stack and stack[-1] != '(' and
precedence.get(stack[-1], 0) >= precedence.get(char, 0)):
output.append(stack.pop())
stack.append(char)
# Pop remaining operators
while stack:
output.append(stack.pop())
return ''.join(output)
# Test cases
expressions = [
"A+B*C",
"A*(B+C)",
"A+B*C-D/E",
"(A+B)*(C-D)"
]
for expr in expressions:
print(f"{expr:20} → {infix_to_postfix(expr)}")Python4. Evaluate Postfix Expression
def evaluate_postfix(expression):
"""
Evaluate a postfix expression
Example: "23*5+" → 11 (2*3 + 5)
"""
stack = []
for char in expression:
if char.isdigit():
stack.append(int(char))
else:
# Pop two operands
operand2 = stack.pop()
operand1 = stack.pop()
# Perform operation
if char == '+':
result = operand1 + operand2
elif char == '-':
result = operand1 - operand2
elif char == '*':
result = operand1 * operand2
elif char == '/':
result = operand1 / operand2
stack.append(result)
return stack.pop()
# Test
expressions = [
("23*5+", "2*3 + 5"),
("53+2*", "(5+3) * 2"),
("234*+5-", "2 + 3*4 - 5")
]
for postfix, infix in expressions:
result = evaluate_postfix(postfix)
print(f"{postfix:10} ({infix:15}) = {result}")Python5. Browser History Implementation
class BrowserHistory:
"""Simulate browser navigation with back/forward buttons"""
def __init__(self, homepage):
self.back_stack = []
self.forward_stack = []
self.current = homepage
def visit(self, url):
"""Visit a new URL"""
self.back_stack.append(self.current)
self.current = url
self.forward_stack.clear() # Clear forward history
print(f"Visiting: {url}")
def back(self):
"""Go back to previous page"""
if not self.back_stack:
print("No pages in back history")
return self.current
self.forward_stack.append(self.current)
self.current = self.back_stack.pop()
print(f"Back to: {self.current}")
return self.current
def forward(self):
"""Go forward to next page"""
if not self.forward_stack:
print("No pages in forward history")
return self.current
self.back_stack.append(self.current)
self.current = self.forward_stack.pop()
print(f"Forward to: {self.current}")
return self.current
def current_page(self):
"""Get current page"""
return self.current
# Example usage
browser = BrowserHistory("google.com")
browser.visit("youtube.com")
browser.visit("github.com")
browser.visit("stackoverflow.com")
print(f"Current: {browser.current_page()}")
browser.back()
browser.back()
print(f"Current: {browser.current_page()}")
browser.forward()
print(f"Current: {browser.current_page()}")Python6. Undo/Redo Functionality
class TextEditor:
"""Text editor with undo/redo functionality"""
def __init__(self):
self.text = ""
self.undo_stack = []
self.redo_stack = []
def write(self, text):
"""Add text"""
self.undo_stack.append(self.text)
self.text += text
self.redo_stack.clear() # Clear redo history
print(f"Text: '{self.text}'")
def undo(self):
"""Undo last change"""
if not self.undo_stack:
print("Nothing to undo")
return
self.redo_stack.append(self.text)
self.text = self.undo_stack.pop()
print(f"After undo: '{self.text}'")
def redo(self):
"""Redo last undone change"""
if not self.redo_stack:
print("Nothing to redo")
return
self.undo_stack.append(self.text)
self.text = self.redo_stack.pop()
print(f"After redo: '{self.text}'")
def get_text(self):
return self.text
# Example usage
editor = TextEditor()
editor.write("Hello")
editor.write(" World")
editor.write("!")
editor.undo()
editor.undo()
editor.redo()
print(f"Final text: '{editor.get_text()}'")PythonCommon Problems
1. Next Greater Element
Find the next greater element for each element in an array.
def next_greater_element(arr):
"""
Find next greater element for each element
Example: [4, 5, 2, 10, 8] → [5, 10, 10, -1, -1]
"""
n = len(arr)
result = [-1] * n
stack = []
# Traverse from right to left
for i in range(n - 1, -1, -1):
# Remove smaller elements
while stack and stack[-1] <= arr[i]:
stack.pop()
# Top of stack is next greater element
if stack:
result[i] = stack[-1]
# Push current element
stack.append(arr[i])
return result
# Test
arr = [4, 5, 2, 10, 8]
result = next_greater_element(arr)
print(f"Array: {arr}")
print(f"Result: {result}")Python2. Stock Span Problem
Calculate the span of stock prices (number of consecutive days before current day with price less than or equal to current).
def stock_span(prices):
"""
Calculate stock span for each day
Example: [100, 80, 60, 70, 60, 75, 85]
→ [1, 1, 1, 2, 1, 4, 6]
"""
n = len(prices)
spans = [0] * n
stack = [] # Store indices
for i in range(n):
# Pop elements while current price is greater
while stack and prices[stack[-1]] <= prices[i]:
stack.pop()
# Calculate span
if not stack:
spans[i] = i + 1
else:
spans[i] = i - stack[-1]
# Push current index
stack.append(i)
return spans
# Test
prices = [100, 80, 60, 70, 60, 75, 85]
spans = stock_span(prices)
print(f"Prices: {prices}")
print(f"Spans: {spans}")Python3. Largest Rectangle in Histogram
Find the area of the largest rectangle in a histogram.
def largest_rectangle_area(heights):
"""
Find largest rectangle area in histogram
Example: [2, 1, 5, 6, 2, 3] → 10
"""
stack = []
max_area = 0
index = 0
while index < len(heights):
# If current bar is higher, push it
if not stack or heights[index] >= heights[stack[-1]]:
stack.append(index)
index += 1
else:
# Calculate area with stack top as smallest bar
top = stack.pop()
width = index if not stack else index - stack[-1] - 1
area = heights[top] * width
max_area = max(max_area, area)
# Pop remaining bars
while stack:
top = stack.pop()
width = index if not stack else index - stack[-1] - 1
area = heights[top] * width
max_area = max(max_area, area)
return max_area
# Test
heights = [2, 1, 5, 6, 2, 3]
print(f"Heights: {heights}")
print(f"Largest rectangle area: {largest_rectangle_area(heights)}")Python4. Valid Parentheses (LeetCode #20)
def is_valid_parentheses(s):
"""
Determine if string has valid parentheses
Example: "()" → True, "([)]" → False
"""
stack = []
mapping = {')': '(', '}': '{', ']': '['}
for char in s:
if char in mapping:
top_element = stack.pop() if stack else '#'
if mapping[char] != top_element:
return False
else:
stack.append(char)
return not stack
# Test cases
test_cases = ["()", "()[]{}", "(]", "([)]", "{[]}"]
for test in test_cases:
print(f"{test:10} → {is_valid_parentheses(test)}")Python5. Min Stack (LeetCode #155)
Design a stack that supports push, pop, top, and retrieving minimum element in constant time.
class MinStack:
"""Stack with O(1) min operation"""
def __init__(self):
self.stack = []
self.min_stack = []
def push(self, val):
self.stack.append(val)
if not self.min_stack or val <= self.min_stack[-1]:
self.min_stack.append(val)
def pop(self):
if self.stack:
val = self.stack.pop()
if val == self.min_stack[-1]:
self.min_stack.pop()
return val
def top(self):
return self.stack[-1] if self.stack else None
def get_min(self):
return self.min_stack[-1] if self.min_stack else None
# Example usage
min_stack = MinStack()
min_stack.push(-2)
min_stack.push(0)
min_stack.push(-3)
print(f"Min: {min_stack.get_min()}") # -3
min_stack.pop()
print(f"Top: {min_stack.top()}") # 0
print(f"Min: {min_stack.get_min()}") # -2Python6. Decode String (LeetCode #394)
def decode_string(s):
"""
Decode encoded string
Example: "3[a]2[bc]" → "aaabcbc"
"3[a2[c]]" → "accaccacc"
"""
stack = []
current_string = ""
current_num = 0
for char in s:
if char.isdigit():
current_num = current_num * 10 + int(char)
elif char == '[':
stack.append((current_string, current_num))
current_string = ""
current_num = 0
elif char == ']':
prev_string, num = stack.pop()
current_string = prev_string + current_string * num
else:
current_string += char
return current_string
# Test cases
test_cases = [
"3[a]2[bc]",
"3[a2[c]]",
"2[abc]3[cd]ef"
]
for test in test_cases:
print(f"{test:20} → {decode_string(test)}")PythonAdvanced Topics
1. Two Stacks in One Array
Implement two stacks using a single array efficiently.
class TwoStacks:
"""Two stacks in one array"""
def __init__(self, size):
self.size = size
self.arr = [None] * size
self.top1 = -1
self.top2 = size
def push1(self, data):
"""Push to stack 1"""
if self.top1 < self.top2 - 1:
self.top1 += 1
self.arr[self.top1] = data
else:
raise OverflowError("Stack Overflow")
def push2(self, data):
"""Push to stack 2"""
if self.top1 < self.top2 - 1:
self.top2 -= 1
self.arr[self.top2] = data
else:
raise OverflowError("Stack Overflow")
def pop1(self):
"""Pop from stack 1"""
if self.top1 >= 0:
data = self.arr[self.top1]
self.top1 -= 1
return data
raise IndexError("Stack 1 Underflow")
def pop2(self):
"""Pop from stack 2"""
if self.top2 < self.size:
data = self.arr[self.top2]
self.top2 += 1
return data
raise IndexError("Stack 2 Underflow")
# Example usage
ts = TwoStacks(10)
ts.push1(1)
ts.push1(2)
ts.push2(10)
ts.push2(20)
print(f"Pop from stack 1: {ts.pop1()}") # 2
print(f"Pop from stack 2: {ts.pop2()}") # 20Python2. Sort a Stack
Sort a stack using only stack operations.
def sort_stack(stack):
"""Sort stack in ascending order (smallest on top)"""
temp_stack = []
while stack:
temp = stack.pop()
while temp_stack and temp_stack[-1] > temp:
stack.append(temp_stack.pop())
temp_stack.append(temp)
# Transfer back to original stack
while temp_stack:
stack.append(temp_stack.pop())
return stack
# Test
stack = [34, 3, 31, 98, 92, 23]
print(f"Original: {stack}")
sorted_stack = sort_stack(stack)
print(f"Sorted: {sorted_stack}")Python3. Stack with Middle Element Operations
class StackWithMiddle:
"""Stack that supports finding/deleting middle element in O(1)"""
class Node:
def __init__(self, data):
self.data = data
self.prev = None
self.next = None
def __init__(self):
self.head = None
self.mid = None
self.count = 0
def push(self, data):
new_node = self.Node(data)
new_node.next = self.head
self.count += 1
if self.count == 1:
self.mid = new_node
else:
self.head.prev = new_node
if self.count % 2 != 0:
self.mid = self.mid.prev
self.head = new_node
def pop(self):
if self.count == 0:
raise IndexError("Stack is empty")
data = self.head.data
self.head = self.head.next
if self.head:
self.head.prev = None
self.count -= 1
if self.count % 2 == 0 and self.mid:
self.mid = self.mid.next
return data
def find_middle(self):
if self.count == 0:
raise IndexError("Stack is empty")
return self.mid.data
def delete_middle(self):
if self.count == 0:
raise IndexError("Stack is empty")
data = self.mid.data
if self.count == 1:
self.head = None
self.mid = None
else:
self.mid.prev.next = self.mid.next
if self.mid.next:
self.mid.next.prev = self.mid.prev
if self.count % 2 == 0:
self.mid = self.mid.prev
else:
self.mid = self.mid.next
self.count -= 1
return data
# Example usage
stack = StackWithMiddle()
for i in range(1, 6):
stack.push(i)
print(f"Pushed {i}, middle: {stack.find_middle()}")Python4. Celebrity Problem
Find the celebrity in a party (person known by everyone but knows no one).
def find_celebrity(matrix):
"""
Find celebrity using stack
matrix[i][j] = 1 means i knows j
Celebrity: column is all 1s (except diagonal), row is all 0s
"""
n = len(matrix)
stack = list(range(n))
# Find potential celebrity
while len(stack) > 1:
a = stack.pop()
b = stack.pop()
if matrix[a][b]: # a knows b
stack.append(b) # a can't be celebrity
else: # a doesn't know b
stack.append(a) # b can't be celebrity
# Verify the potential celebrity
candidate = stack.pop()
for i in range(n):
if i != candidate:
if matrix[candidate][i] or not matrix[i][candidate]:
return -1 # No celebrity
return candidate
# Test
matrix = [
[0, 1, 0],
[0, 0, 0],
[0, 1, 0]
]
celebrity = find_celebrity(matrix)
print(f"Celebrity: {celebrity}") # Person 1Python5. Expression Evaluation with Operator Precedence
Complete expression evaluator with proper operator precedence.
def evaluate_expression(expression):
"""
Evaluate mathematical expression with proper precedence
Example: "3 + 5 * 2" → 13
"""
def apply_operation(operators, values):
operator = operators.pop()
right = values.pop()
left = values.pop()
if operator == '+':
values.append(left + right)
elif operator == '-':
values.append(left - right)
elif operator == '*':
values.append(left * right)
elif operator == '/':
values.append(left / right)
def precedence(op):
if op in '+-':
return 1
if op in '*/':
return 2
return 0
values = []
operators = []
i = 0
while i < len(expression):
if expression[i] == ' ':
i += 1
continue
# Number
if expression[i].isdigit():
num = 0
while i < len(expression) and expression[i].isdigit():
num = num * 10 + int(expression[i])
i += 1
values.append(num)
continue
# Opening parenthesis
if expression[i] == '(':
operators.append(expression[i])
# Closing parenthesis
elif expression[i] == ')':
while operators and operators[-1] != '(':
apply_operation(operators, values)
operators.pop() # Remove '('
# Operator
else:
while (operators and operators[-1] != '(' and
precedence(operators[-1]) >= precedence(expression[i])):
apply_operation(operators, values)
operators.append(expression[i])
i += 1
# Apply remaining operators
while operators:
apply_operation(operators, values)
return values[-1]
# Test cases
expressions = [
"3 + 5 * 2",
"10 + 2 * 6",
"100 * 2 + 12",
"100 * ( 2 + 12 )",
"100 * ( 2 + 12 ) / 14"
]
for expr in expressions:
result = evaluate_expression(expr)
print(f"{expr:25} = {result}")PythonStack Interview Questions Checklist
Easy Level
- ✓ Implement stack using arrays
- ✓ Implement stack using linked list
- ✓ Valid parentheses
- ✓ Reverse a string using stack
- ✓ Implement two stacks in an array
Medium Level
- ✓ Min stack
- ✓ Next greater element
- ✓ Stock span problem
- ✓ Infix to postfix conversion
- ✓ Evaluate postfix expression
- ✓ Sort a stack
- ✓ Decode string
Hard Level
- ✓ Largest rectangle in histogram
- ✓ Maximal rectangle
- ✓ Celebrity problem
- ✓ Expression evaluation
- ✓ Stack with middle element operations
Best Practices
1. When to Use Stack
- Function call management (recursion)
- Expression evaluation and parsing
- Backtracking algorithms (DFS, maze solving)
- Undo/redo operations
- Browser history navigation
- Syntax parsing and validation
2. Common Pitfalls
# ❌ Don't forget to check if stack is empty before pop/peek
stack.pop() # May raise error if empty
# ✓ Always check before popping
if stack:
stack.pop()
# ✓ Or handle exceptions
try:
stack.pop()
except IndexError:
print("Stack is empty")Python3. Memory Optimization
# Use deque instead of list for better performance
from collections import deque
# ❌ Less efficient for large stacks
stack = []
# ✓ More efficient
stack = deque()Python4. Type Hints and Documentation
from typing import List, Optional, Any
class Stack:
"""
A LIFO (Last-In-First-Out) stack implementation.
Attributes:
_items: List storing stack elements
"""
def __init__(self) -> None:
self._items: List[Any] = []
def push(self, item: Any) -> None:
"""Add item to top of stack."""
self._items.append(item)
def pop(self) -> Any:
"""Remove and return top item."""
if self.is_empty():
raise IndexError("pop from empty stack")
return self._items.pop()
def peek(self) -> Optional[Any]:
"""Return top item without removing."""
return self._items[-1] if self._items else None
def is_empty(self) -> bool:
"""Check if stack is empty."""
return len(self._items) == 0
def size(self) -> int:
"""Return number of items in stack."""
return len(self._items)PythonSummary
Key Takeaways
- LIFO Principle: Last element in is first element out
- O(1) Operations: Push, pop, and peek are constant time
- Multiple Implementations: List, deque, linked list, LifoQueue
- Wide Applications: Expression parsing, backtracking, history management
- Interview Favorite: Common in coding interviews and algorithm problems
Quick Reference
# Create a stack
stack = []
# Basic operations
stack.append(item) # Push
item = stack.pop() # Pop
item = stack[-1] # Peek
is_empty = len(stack) == 0
size = len(stack)
# Using deque (recommended)
from collections import deque
stack = deque()
stack.append(item) # Push
item = stack.pop() # PopPythonFurther Reading
- Time and Space Complexity Analysis
- Recursion and Call Stack
- Stack-based Memory Management
- Advanced Data Structures (Monotonic Stack)
- Compiler Design and Expression Parsing
Practice Resources:
- LeetCode Stack Problems
- HackerRank Stack Challenges
- GeeksforGeeks Stack Articles
- Project Euler Stack Problems
Happy Coding! 🚀
Discover more from Altgr Blog
Subscribe to get the latest posts sent to your email.
