1.
Why Python data structures matter in LeetCode
In LeetCode, many problems are solved not by complicated syntax, but by selecting the
correct data structure.
For example:
• a brute-force solution may be O(n²)
• using a set can reduce lookup to O(1)
• using a dict can reduce repeated searches
• using a deque can make queue operations efficient
• using heapq helps when repeated minimum or maximum access is needed
• using Counter simplifies frequency counting
In Python, especially, good use of built-in data structures often makes solutions much
shorter, cleaner, and faster.
2. LIST
What is a list?
A Python list is a dynamic array-like data structure. It can store elements of different types,
though in LeetCode we usually store same-type elements.
nums = [1, 2, 3, 4]
Why list is extremely important in LeetCode
Most LeetCode inputs in Python are given as lists:
• List[int]
• List[str]
• List[List[int]]
Lists are used for:
• arrays
• stacks
• dynamic result storage
• matrix representation
• graph adjacency lists
• backtracking paths
Time complexity
• Access by index: O(1)
• Update by index: O(1)
• Append at end: O(1) amortized
• Pop at end: O(1)
• Insert at beginning/middle: O(n)
• Pop from beginning: O(n)
• Search: O(n)
Important methods
• append(x)
• extend(iterable)
• insert(i, x)
• pop()
• pop(i)
• remove(x)
• index(x)
• count(x)
• sort()
• reverse()
• copy()
Example
nums = [10, 20, 30]
print(nums[1]) # 20
nums[1] = 50
print(nums) # [10, 50, 30]
[Link](70)
print(nums) # [10, 50, 30, 70]
[Link]()
print(nums) # [10, 50, 30]
Common LeetCode use cases
a) Traversal
for x in nums:
print(x)
b) Index-based loop
for i in range(len(nums)):
print(i, nums[i])
c) Backtracking path
path = []
[Link](1)
[Link](2)
[Link]()
d) Matrix
grid = [
[1, 2],
[3, 4]
]
print(grid[1][0]) # 3
Common mistakes
Mistake 1: using pop(0) repeatedly
q = [1, 2, 3]
[Link](0) # O(n)
This is slow for queue behavior. Use [Link] instead.
Mistake 2: shallow copy in nested lists
grid = [[0] * 3] * 4
All rows refer to the same list.
Wrong behavior:
grid[0][0] = 1
print(grid)
# [[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
Correct:
grid = [[0] * 3 for _ in range(4)]
3. TUPLE
What is a tuple?
A tuple is an immutable ordered collection.
point = (2, 3)
Why tuple matters in LeetCode
Tuples are useful when:
• you want fixed grouped values
• you need hashable composite keys in set or dict
• you want to store coordinates like (r, c)
• you push structured items into heaps
Time complexity
• Access by index: O(1)
• Search: O(n)
• Cannot modify after creation
Example
p = (10, 20)
print(p[0]) # 10
Important use cases
a) coordinate storage
visited = set()
[Link]((2, 3))
b) heap elements
import heapq
heap = []
[Link](heap, (2, "taskA"))
[Link](heap, (1, "taskB"))
print([Link](heap)) # (1, 'taskB')
c) returning multiple values
def get_pair():
return (4, 5)
Common mistake
Trying to modify tuple:
t = (1, 2)
# t[0] = 10 # error
4. STRING
What is a string?
A string is an immutable sequence of characters.
s = "hello"
Why string handling matters in LeetCode
Very common in:
• palindrome problems
• substring problems
• anagrams
• parsing
• sliding window
• stack-based decoding
• string building
Time complexity
• Access by index: O(1)
• Slice: usually O(k)
• Concatenation repeatedly in loop can be inefficient
Important operations
• len(s)
• s[i]
• s[start:end]
• [Link]()
• [Link]()
• [Link]()
• [Link]()
• ''.join(list_of_strings)
• [Link](sub)
• [Link](ch)
Example
s = "hello"
print(s[1]) #e
print(s[:4]) # hell
print(s[::-1]) # olleh
Important note: strings are immutable
Wrong:
s[0] = 'H'
Correct ways:
s = 'H' + s[1:]
or
chars = list(s)
chars[0] = 'H'
s = ''.join(chars)
Efficient string building
Bad:
ans = ""
for ch in ['a', 'b', 'c']:
ans += ch
Better:
chars = []
for ch in ['a', 'b', 'c']:
[Link](ch)
ans = ''.join(chars)
5. SET
What is a set?
A set stores unique elements using hashing.
seen = {1, 2, 3}
or
seen = set()
Why set is important in LeetCode
Set is one of the most frequently used Python data structures for:
• duplicate checking
• membership testing
• visited tracking
• removing duplicates logically
• sliding window uniqueness
Time complexity
Average case:
• Add: O(1)
• Remove: O(1)
• Contains: O(1)
Important methods
• add(x)
• remove(x) → error if absent
• discard(x) → no error if absent
• pop()
• clear()
• union()
• intersection()
• difference()
Example
s = set()
[Link](10)
[Link](20)
[Link](10)
print(s) # {10, 20}
print(20 in s) # True
LeetCode examples
a) Contains Duplicate
def containsDuplicate(nums):
seen = set()
for x in nums:
if x in seen:
return True
[Link](x)
return False
b) Longest Consecutive Sequence
def longestConsecutive(nums):
num_set = set(nums)
best = 0
for x in num_set:
if x - 1 not in num_set:
length = 1
while x + length in num_set:
length += 1
best = max(best, length)
return best
Common mistakes
Mistake 1: adding unhashable types
s = set()
# [Link]([1, 2]) # error: list is unhashable
Use tuple instead:
[Link]((1, 2))
Mistake 2: using remove() when key may not exist
[Link](10) # can raise KeyError
Safer:
[Link](10)
6. FROZENSET
What is frozenset?
An immutable version of set.
fs = frozenset([1, 2, 3])
Why it matters
Less common, but useful when:
• you need a set-like object as a key in another set/dict
• representing immutable groups
Example
a = frozenset([1, 2])
b = frozenset([2, 3])
s = {a, b}
print(s)
LeetCode relevance
Rare, but sometimes useful in state compression or memoization where the state is an
unordered group.
7. DICT
What is a dict?
A dict stores key-value pairs using hashing.
mp = {"a": 1, "b": 2}
Why dict is extremely important in LeetCode
Probably the single most useful Python structure after list.
Used for:
• frequency counting
• index lookup
• grouping
• adjacency lists
• memoization
• prefix sum tracking
• dynamic mapping
Time complexity
Average case:
• Insert/update: O(1)
• Access: O(1)
• Delete: O(1)
• Membership in keys: O(1)
Important methods
• d[key] = value
• [Link](key, default)
• [Link](key, default)
• [Link]()
• [Link]()
• [Link]()
• key in d
Example
mp = {}
mp[1] = 100
mp[2] = 200
print(mp[1]) # 100
print([Link](3, 0)) # 0
Important LeetCode patterns
a) value to index map
def twoSum(nums, target):
mp = {}
for i, x in enumerate(nums):
need = target - x
if need in mp:
return [mp[need], i]
mp[x] = i
b) frequency map
freq = {}
for x in nums:
freq[x] = [Link](x, 0) + 1
c) character count
count = {}
for ch in s:
count[ch] = [Link](ch, 0) + 1
d) grouping
groups = {}
for word in strs:
key = ''.join(sorted(word))
if key not in groups:
groups[key] = []
groups[key].append(word)
Iterating over dict
keys
for key in mp:
print(key, mp[key])
items
for key, value in [Link]():
print(key, value)
Common mistakes
Mistake 1: direct access without checking
freq[x] += 1
This fails if x not present.
Use:
freq[x] = [Link](x, 0) + 1
Mistake 2: confusing in dict
if x in mp:
This checks keys, not values.
8. DEFAULTDICT
What is defaultdict?
A special dictionary from collections that provides a default value automatically.
from collections import defaultdict
Syntax
d = defaultdict(int)
Here, missing keys default to 0.
Common types
• defaultdict(int) → default 0
• defaultdict(list) → default []
• defaultdict(set) → default set()
Why it is useful in LeetCode
It simplifies code for:
• counting
• grouping
• graph adjacency
• collections of lists/sets
Example 1: counting
from collections import defaultdict
freq = defaultdict(int)
for x in [1, 2, 2, 3]:
freq[x] += 1
print(freq) # defaultdict(<class 'int'>, {1: 1, 2: 2, 3: 1})
Example 2: grouping anagrams
from collections import defaultdict
groups = defaultdict(list)
for word in ["eat", "tea", "tan", "ate", "nat", "bat"]:
key = ''.join(sorted(word))
groups[key].append(word)
print(list([Link]()))
Example 3: graph adjacency list
from collections import defaultdict
graph = defaultdict(list)
edges = [(0, 1), (0, 2), (1, 3)]
for u, v in edges:
graph[u].append(v)
print(graph[0]) # [1, 2]
Common mistake
A defaultdict creates missing keys when accessed.
d = defaultdict(int)
print(d[10]) # creates key 10 with value 0
Sometimes this is okay, sometimes it changes dictionary size unexpectedly.
9. COUNTER
What is Counter?
Counter is a special dictionary for frequency counting.
from collections import Counter
Why Counter is useful
It makes frequency-based LeetCode problems much simpler.
Example
from collections import Counter
freq = Counter([1, 2, 2, 3, 3, 3])
print(freq) # Counter({3: 3, 2: 2, 1: 1})
Useful methods
• Counter(iterable)
• freq[x]
• most_common(k)
• arithmetic-like operations on counters
Example 1: Valid Anagram
from collections import Counter
def isAnagram(s, t):
return Counter(s) == Counter(t)
Example 2: Top K frequent
from collections import Counter
freq = Counter(nums)
print(freq.most_common(2))
Example 3: direct frequency access
freq = Counter("banana")
print(freq['a']) # 3
When to use Counter
Use it when:
• problem is mainly counting
• readability matters
• you want concise code
When not to use Counter
Sometimes manual dict counting is better if:
• you need custom behavior
• performance tuning matters deeply
• interviewer expects explicit logic
10. DEQUE
What is deque?
deque stands for double-ended queue. It comes from collections.
from collections import deque
It supports efficient insertion and removal from both ends.
Why deque is extremely important in LeetCode
It is used for:
• queue operations
• BFS
• sliding window maximum
• monotonic queue
• stack-like operations
• palindrome style two-end processing
Time complexity
• append(): O(1)
• appendleft(): O(1)
• pop(): O(1)
• popleft(): O(1)
Important methods
• append(x)
• appendleft(x)
• pop()
• popleft()
• peek is done by indexing like dq[0] or dq[-1]
Example
from collections import deque
dq = deque()
[Link](10)
[Link](20)
[Link](5)
print(dq) # deque([5, 10, 20])
print([Link]()) # 5
print([Link]()) # 20
Queue usage
from collections import deque
q = deque()
[Link](1)
[Link](2)
print([Link]()) # 1
Stack usage
st = deque()
[Link](10)
[Link](20)
print([Link]()) # 20
BFS example
from collections import deque
def bfs(graph, start):
q = deque([start])
visited = {start}
while q:
node = [Link]()
print(node)
for nei in graph[node]:
if nei not in visited:
[Link](nei)
[Link](nei)
Sliding window maximum pattern
from collections import deque
def maxSlidingWindow(nums, k):
dq = deque()
ans = []
for i, x in enumerate(nums):
while dq and dq[0] <= i - k:
[Link]()
while dq and nums[dq[-1]] < x:
[Link]()
[Link](i)
if i >= k - 1:
[Link](nums[dq[0]])
return ans
Common mistake
Using list as queue:
q = []
[Link](1)
[Link](0) # slow
Use deque:
q = deque()
[Link](1)
[Link]()
11. STACK IN PYTHON
Is there a separate stack type?
Python does not have a special built-in Stack class for most LeetCode work. Usually we use:
• list as stack
• sometimes deque as stack
Best practice
For most stack problems, use list.
stack = []
[Link](10) # push
[Link](20)
print([Link]()) # 20
Time complexity
• push (append): O(1)
• pop from end: O(1)
• peek: stack[-1] is O(1)
Example: Valid Parentheses
def isValid(s):
stack = []
pairs = {')': '(', ']': '[', '}': '{'}
for ch in s:
if ch in '([{':
[Link](ch)
else:
if not stack or stack[-1] != pairs[ch]:
return False
[Link]()
return not stack
Common stack problems
• Valid Parentheses
• Next Greater Element
• Daily Temperatures
• Decode String
• Largest Rectangle in Histogram
• Remove K Digits
• Monotonic stack problems
list vs deque for stack
Usually:
• list is perfectly fine for stack
• deque also works
• list is simpler and very common
12. QUEUE IN PYTHON
What should be used as queue?
For queue in Python, use [Link].
Why not use list?
Because removing from front is slow:
• [Link](0) is O(n)
With deque:
• popleft() is O(1)
Example
from collections import deque
q = deque()
[Link](10)
[Link](20)
print([Link]()) # 10
LeetCode use cases
• BFS in trees
• BFS in graphs
• shortest path in unweighted graph
• rotting oranges
• level order traversal
• topological sort
Example: binary tree level order
from collections import deque
def levelOrder(root):
if not root:
return []
q = deque([root])
result = []
while q:
level = []
for _ in range(len(q)):
node = [Link]()
[Link]([Link])
if [Link]:
[Link]([Link])
if [Link]:
[Link]([Link])
[Link](level)
return result
13. HEAPQ
What is heapq?
Python’s heapq module implements a min-heap.
import heapq
Why it is important in LeetCode
Used for:
• Kth smallest/largest
• top k elements
• scheduling
• merge k sorted lists
• Dijkstra
• greedy problems
• median-like processing
Time complexity
• push: O(log n)
• pop: O(log n)
• peek smallest: O(1) via heap[0]
Important methods
• [Link](heap, x)
• [Link](heap)
• [Link](lst)
• [Link](heap, x)
• [Link](k, iterable)
• [Link](k, iterable)
Example
import heapq
heap = []
[Link](heap, 5)
[Link](heap, 1)
[Link](heap, 3)
print(heap[0]) #1
print([Link](heap)) # 1
print([Link](heap)) # 3
Heapify example
import heapq
nums = [4, 1, 7, 2]
[Link](nums)
print(nums[0]) # smallest element
Max heap in Python
Python heapq is min-heap by default. To simulate max-heap, store negative values.
import heapq
heap = []
for x in [5, 1, 10]:
[Link](heap, -x)
print(-[Link](heap)) # 10
Example: Kth largest
import heapq
def findKthLargest(nums, k):
heap = []
for x in nums:
[Link](heap, x)
if len(heap) > k:
[Link](heap)
return heap[0]
Heap of tuples
import heapq
heap = []
[Link](heap, (2, "taskB"))
[Link](heap, (1, "taskA"))
print([Link](heap)) # (1, 'taskA')
Python compares tuple elements lexicographically.
Common mistakes
Mistake 1: expecting full sorted order
A heap is not a fully sorted list. Only heap[0] is guaranteed smallest.
Mistake 2: trying max-heap directly
Need negation or custom pattern.
14. BISECT
What is bisect?
The bisect module helps with binary search in sorted lists.
import bisect
Why useful in LeetCode
Used when:
• data is sorted
• you need insertion position
• you need lower bound / upper bound
• solving binary-search-like ordered problems
Important functions
• bisect.bisect_left(arr, x)
• bisect.bisect_right(arr, x)
• [Link](arr, x)
Example
import bisect
arr = [1, 2, 4, 4, 5]
print(bisect.bisect_left(arr, 4)) # 2
print(bisect.bisect_right(arr, 4)) # 4
Meaning
• bisect_left: first valid insertion index
• bisect_right: insertion index after all equal elements
Example: search insert position
import bisect
def searchInsert(nums, target):
return bisect.bisect_left(nums, target)
Example: maintain sorted list
import bisect
arr = [1, 3, 5]
[Link](arr, 4)
print(arr) # [1, 3, 4, 5]
Important limitation
Insertion into list is still O(n) because elements must shift.
So bisect gives fast searching, not always fast insertion overall.
15. SORTED LIST PATTERN IN PYTHON
Python standard library does not provide a full balanced BST like Java’s TreeSet or TreeMap.
This is important.
So what do Python LeetCode solutions do?
Usually one of these:
• use a sorted list + bisect
• use heapq when only min/max needed
• use a set/dict if ordering not needed
• in rare cases, use third-party sortedcontainers locally, but not in LeetCode unless
allowed
• redesign logic to avoid needing a tree structure
If sorted dynamic order is needed
Example:
• maintain sorted list
• use bisect_left / bisect_right
But insertion/deletion in middle remains O(n).
This is why some Java TreeSet solutions do not translate directly to Python as efficiently.
16. COUNTER + HEAPQ COMBINATION
This is a very important LeetCode combination.
Example: Top K Frequent Elements
from collections import Counter
import heapq
def topKFrequent(nums, k):
freq = Counter(nums)
heap = []
for num, count in [Link]():
[Link](heap, (count, num))
if len(heap) > k:
[Link](heap)
return [num for count, num in heap]
This combination appears in many problems.
17. DICT + LIST COMBINATION
Another common pattern.
Example: Group Anagrams
from collections import defaultdict
def groupAnagrams(strs):
groups = defaultdict(list)
for word in strs:
key = ''.join(sorted(word))
groups[key].append(word)
return list([Link]())
Example: graph adjacency
from collections import defaultdict
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
graph[v].append(u)
18. SET + QUEUE COMBINATION
Used heavily in BFS and graph traversal.
Example
from collections import deque
def bfs(graph, start):
q = deque([start])
visited = {start}
while q:
node = [Link]()
for nei in graph[node]:
if nei not in visited:
[Link](nei)
[Link](nei)
Why both?
• queue controls processing order
• visited set prevents repeated processing
19. LIST AS MATRIX
A matrix in Python is usually represented as a list of lists.
grid = [
[1, 2, 3],
[4, 5, 6]
]
Access
print(grid[1][2]) # 6
Traversal
rows = len(grid)
cols = len(grid[0])
for r in range(rows):
for c in range(cols):
print(grid[r][c])
Common LeetCode use cases
• number of islands
• flood fill
• matrix traversal
• DP tables
• shortest path in grid
• spiral matrix
Important matrix initialization
Correct
dp = [[0] * m for _ in range(n)]
Wrong
dp = [[0] * m] * n
20. GRAPH REPRESENTATION
Graphs in Python are often represented using:
• dict of lists
• defaultdict(list)
• list of lists if node count fixed and nodes are 0 to n-1
Example: adjacency list with fixed nodes
n=5
graph = [[] for _ in range(n)]
edges = [(0, 1), (0, 2), (1, 3)]
for u, v in edges:
graph[u].append(v)
Example: defaultdict
from collections import defaultdict
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
graph[v].append(u)
When to use what?
Use list of lists when:
• nodes are integer indexed
• node count known
• faster and simple
Use defaultdict(list) when:
• labels may be arbitrary
• graph sparse and flexible
• dynamic building easier
21. CUSTOM OBJECTS
Python allows custom classes, but in LeetCode most solutions use tuples, dicts, and lists more
often.
Still, custom objects matter sometimes.
Example
class NodeState:
def __init__(self, node, dist):
[Link] = node
[Link] = dist
Hashability issue
If you want to put custom objects into sets or dict keys, you need proper hashing/equality
behavior.
Usually easier:
• use tuples instead of custom objects
Example:
visited = set()
[Link]((row, col))
instead of custom class coordinates.
For heaps
Tuples are again usually easier:
[Link](heap, (dist, node))
22. COMMON LEETCODE DATA STRUCTURE PATTERNS IN PYTHON
Now let us map problem patterns to Python data structures.
Pattern 1: set for duplicate detection
Problem type
Need to know whether something has already appeared.
Example
def containsDuplicate(nums):
seen = set()
for x in nums:
if x in seen:
return True
[Link](x)
return False
Pattern 2: dict for frequency counting
Problem type
Need count of occurrences.
Example
def count_freq(nums):
freq = {}
for x in nums:
freq[x] = [Link](x, 0) + 1
return freq
Or:
from collections import Counter
freq = Counter(nums)
Pattern 3: dict for index lookup
Problem type
Need previous occurrence quickly.
Example
def twoSum(nums, target):
mp = {}
for i, x in enumerate(nums):
need = target - x
if need in mp:
return [mp[need], i]
mp[x] = i
Pattern 4: list as stack
Problem type
Matching symbols or nearest greater/smaller.
Example
def isValid(s):
st = []
pairs = {')': '(', ']': '[', '}': '{'}
for ch in s:
if ch in '([{':
[Link](ch)
else:
if not st or st[-1] != pairs[ch]:
return False
[Link]()
return not st
Pattern 5: deque as queue for BFS
Problem type
Level order, shortest path in unweighted graph, traversal.
Example
from collections import deque
def bfs(graph, start):
q = deque([start])
seen = {start}
while q:
node = [Link]()
for nei in graph[node]:
if nei not in seen:
[Link](nei)
[Link](nei)
Pattern 6: deque as monotonic queue
Problem type
Sliding window maximum/minimum.
Already shown above.
Pattern 7: heapq for top-k or repeated min extraction
Example
import heapq
def kthSmallest(nums, k):
[Link](nums)
for _ in range(k - 1):
[Link](nums)
return [Link](nums)
Pattern 8: tuple as composite key
Problem type
Need coordinate/state identity.
Example
visited = set()
[Link]((r, c, mask))
23. WHEN TO USE WHAT
This is one of the most important sections.
Use list when:
• you need dynamic array behavior
• random index access matters
• building answers
• using stack
• storing graph adjacency lists
Use tuple when:
• data should not change
• composite key needed in set/dict
• heap elements need multiple fields
• coordinates/states
Use set when:
• uniqueness matters
• fast membership test needed
• duplicate detection
• visited tracking
Use dict when:
• key-value mapping needed
• frequency counts
• lookup of previous positions
• grouping
• adjacency mapping
Use defaultdict when:
• you repeatedly initialize missing keys
• grouping into lists/sets
• adjacency lists
• counting
Use Counter when:
• frequency counting is the main task
• concise code helps
Use deque when:
• queue needed
• BFS
• popleft required
• sliding window maximum
• double-ended operations needed
Use heapq when:
• repeated smallest element needed
• top-k logic
• scheduling
• greedy extraction
• Dijkstra
Use bisect when:
• sorted list is given or maintained
• you need insertion/search position
• binary search boundary logic
24. IMPORTANT DIFFERENCES
list vs deque
list
• good for stack
• good for random access
• bad for queue front removal
deque
• excellent for queue
• excellent for both-end operations
• not ideal for frequent random indexing
Use:
• list for stack
• deque for queue/BFS/sliding window
dict vs defaultdict
dict
• explicit control
• missing key raises KeyError
defaultdict
• simpler for grouped/default behavior
• auto-creates missing entries
Use:
• dict when you want full control
• defaultdict when missing-key initialization is repetitive
dict counting vs Counter
dict
• explicit and flexible
Counter
• concise and powerful for pure counting
Use:
• Counter for frequency-heavy problems
• dict if custom logic needed
set vs dict
set
• stores only keys / unique values
dict
• stores key-value associations
Use:
• set when only existence matters
• dict when additional info must be stored
heapq vs sorting
sorting
• good if you need full sorted order once
heapq
• good when repeatedly extracting smallest/largest
• good for streaming/top-k problems
25. COMMON LEETCODE PROBLEMS MAPPED TO PYTHON DATA STRUCTURES
set
• Contains Duplicate
• Longest Consecutive Sequence
• Happy Number
• visited in graph/grid problems
dict
• Two Sum
• Isomorphic Strings
• Subarray Sum Equals K
• Copy List with Random Pointer
• LRU-cache-like logic conceptually
Counter
• Valid Anagram
• Top K Frequent Elements
• Find All Anagrams in a String
• Majority Element style counting
deque
• Binary Tree Level Order Traversal
• Rotting Oranges
• Sliding Window Maximum
• Word Ladder
• 0-1 BFS variants
list as stack
• Valid Parentheses
• Daily Temperatures
• Next Greater Element
• Decode String
• Largest Rectangle in Histogram
heapq
• Kth Largest Element
• Merge K Sorted Lists
• Meeting Rooms II
• Find Median from Data Stream
• Dijkstra
bisect
• Search Insert Position
• binary search boundary problems
• maintaining sorted lists
26. ITERATION PATTERNS YOU MUST KNOW
List
for x in nums:
print(x)
List with index
for i, x in enumerate(nums):
print(i, x)
Dict keys
for k in mp:
print(k, mp[k])
Dict items
for k, v in [Link]():
print(k, v)
Set
for x in seen:
print(x)
Matrix
for r in range(len(grid)):
for c in range(len(grid[0])):
print(grid[r][c])
27. MEMORY AND COPYING PITFALLS
This is very important in Python.
Simple list copy
Wrong if aliasing not intended
a = [1, 2, 3]
b=a
[Link](4)
print(a) # [1, 2, 3, 4]
Correct shallow copy
b = a[:]
or
b = list(a)
or
b = [Link]()
Nested lists
For nested structures, shallow copy may not be enough.
Example
a = [[1], [2]]
b = [Link]()
b[0].append(99)
print(a) # [[1, 99], [2]]
Need deep copy if full separation is required:
import copy
b = [Link](a)
Backtracking important rule
When storing a current path:
[Link](path[:])
not
[Link](path)
Because path changes later.
28. HASHABILITY RULES
Very important for set and dict keys.
Hashable
• int
• str
• tuple (if all contents hashable)
• frozenset
Not hashable
• list
• set
• dict
Wrong
visited = set()
# [Link]([1, 2]) # error
Correct
[Link]((1, 2))
29. COMMON PERFORMANCE ADVICE FOR PYTHON IN LEETCODE
1. Use set and dict for fast lookups.
2. Use deque for BFS and queue behavior.
3. Use list for stack.
4. Use heapq for top-k and repeated min extraction.
5. Use Counter or defaultdict(int) for frequencies.
6. Avoid pop(0) on list.
7. Avoid repeated string concatenation in loops for large strings.
8. Use tuples for visited states and coordinates.
9. Be careful with shallow copies.
10. Prefer built-in structures over overcomplicated custom classes unless truly needed
30. A VERY PRACTICAL CHOOSING GUIDE
Ask yourself these questions.
Do I need fast membership lookup?
Use set or dict
Do I need counts/frequencies?
Use Counter, dict, or defaultdict(int)
Do I need key-value mapping?
Use dict
Do I need uniqueness only?
Use set
Do I need FIFO processing?
Use deque
Do I need LIFO processing?
Use list as stack
Do I need repeated minimum/maximum extraction?
Use heapq
Do I need ordered search positions in a sorted sequence?
Use bisect
Do I need a composite state as a key?
Use tuple
Do I need to build a matrix or adjacency list?
Use nested list or defaultdict(list)
31. FINAL SUMMARY TABLE
list
Dynamic array, stack, matrix, backtracking path, adjacency list
tuple
Immutable grouped values, hashable composite keys, coordinates, heap items
string
Immutable character sequence, slicing, parsing, substring logic
set
Unique elements, fast existence checking, visited tracking
frozenset
Immutable set, hashable state/group representation
dict
Fast key-value mapping, frequencies, indices, grouping
defaultdict
Automatic default values, grouping, graph building, counting
Counter
Frequency counting made easy
deque
Efficient queue and both-end operations, BFS, sliding window
heapq
Min-heap, top-k, greedy extraction, Dijkstra, scheduling
bisect
Binary search on sorted lists, insertion boundaries