heapq implements min heap, providing O(log n) push/pop operations. Used for priority queues, finding n smallest/largest elements, and scheduling tasks. Methods include heappush(), heappop(), heapify(). Can implement max heap by negating values.
Python uses Timsort, hybrid of merge sort and insertion sort. Stable sort with O(n log n) worst case. Adaptive algorithm that performs well on real-world data with partially ordered sequences. Minimizes comparisons using galloping mode.
Counter from collections creates dictionary subclass for counting hashable objects. Supports addition, subtraction, intersection, union. Methods: most_common(), elements(). Useful for frequency counting and multisets.
Implement iteratively or recursively on sorted sequence. Handle mid calculation, comparison, and boundary updates. Time complexity O(log n). Consider bisect module for built-in implementation. Handle edge cases and duplicates.
Lists are dynamic arrays that can store elements of different types. Arrays (from array module) store homogeneous data, are more memory efficient, and support mathematical operations. Lists offer more flexibility but use more memory due to storing references.
Implement using class with Node class (value, left, right pointers) and Tree class with insert, delete, search methods. Balance tree using rotations. Time complexity O(log n) average case, O(n) worst case for unbalanced tree.
Deques (collections.deque) are double-ended queues supporting O(1) append/pop at both ends. Used for sliding windows, maintain last n items, implement queues/stacks efficiently. More efficient than lists for these operations.
Create Node class with value and next pointer. LinkedList class manages head pointer, implements insert, delete, traverse methods. Optional: add tail pointer for O(1) append. Consider implementing iterator protocol for traversal.
Represent graphs using adjacency lists (dictionaries) or matrices. Implement BFS/DFS using queue/stack. Use dict/set for visited nodes. Consider weight handling for Dijkstra/shortest paths. Implement path finding and cycle detection.
Create TrieNode class with children dict and is_end flag. Implement insert, search, startswith methods. Use dict for child nodes. Time complexity O(m) for operations where m is key length. Useful for autocomplete, spell check.
append() adds single element, extend() adds elements from iterable. append([1,2]) adds list as single element, extend([1,2]) adds individual elements. extend() equivalent to += operator. Consider memory and performance implications.
Implement find and union operations using dictionary/array. Use path compression and union by rank optimizations. Time complexity nearly O(1) with optimizations. Used in Kruskal's algorithm, connected components.
Use immutable types (strings, numbers, tuples of immutables). Consider hash collisions and distribution. Custom objects need __hash__ and __eq__. Avoid mutable keys that could change hash value.
Average case time complexities for dictionary operations are: Get item O(1), Set item O(1), Delete item O(1), Search O(1). However, worst case can be O(n) due to hash collisions. Dictionary uses hash table implementation for efficient access.
Tuples are immutable, slightly more memory efficient, can be dictionary keys. Lists are mutable, support item assignment, have more methods. Tuples often used for returning multiple values, representing fixed collections.
bytearray is mutable version of bytes. Supports in-place modifications, useful for building binary data incrementally. Methods like append(), extend(), reverse(). Consider for large binary data manipulation.
Use heapq module for min heap implementation. Wrap elements in tuples with priority. Alternative: queue.PriorityQueue for thread-safe version. Operations: push O(log n), pop O(log n). Handle custom comparison.
String concatenation with += creates new string objects. Use join() method for multiple concatenations, more efficient. For building strings, consider list of strings or io.StringIO. String interning affects memory usage.
In Python 2, range creates list, xrange creates iterator object. Python 3's range is like xrange, memory efficient iterator. Use for loops, sequence generation. Consider memory usage for large ranges.
Quicksort: partition around pivot, recursively sort subarrays. Mergesort: divide array, sort recursively, merge sorted halves. Consider in-place vs new array, stability requirements, pivot selection strategies.
itertools provides efficient iteration tools: combinations(), permutations(), product(), cycle(), chain(). Memory efficient iterators for combinatorial operations. Used in generating test cases, processing sequences.
sorted() creates new sorted list, leaving original unchanged. list.sort() modifies list in-place. Both use Timsort algorithm, accept key function and reverse parameter. sorted() works on any iterable, while sort() is list-only method.
bisect module provides binary search functionality for sorted sequences. bisect_left finds insertion point for element to maintain sort order, bisect_right finds rightmost position. O(log n) time complexity. Useful for maintaining sorted sequences.
Sets use hash tables with open addressing to handle collisions. When collision occurs, probing finds next empty slot. Load factor determines resize threshold. Set operations (union, intersection) are optimized using hash-based algorithms.
OrderedDict maintains insertion order (pre-3.7), useful for LRU caches. defaultdict provides default values for missing keys, simplifying handling of nested structures and counters. Both from collections module.
Use memoization (decorator or dict) or tabulation (arrays). Handle base cases, build solution using smaller subproblems. Consider space optimization using rolling arrays. Common in optimization problems.
Python uses open addressing with random probing. Alternative methods: chaining (linked lists), linear probing, quadratic probing. Load factor determines rehashing. Performance depends on hash function quality and collision resolution.
Stack: use append() and pop() for LIFO. Queue: use append() and pop(0)/list.pop(0) for FIFO (inefficient, use collections.deque instead). Consider implementing size limits and empty checks.
Use decorator with cache dict, or functools.lru_cache. Store function arguments as keys. Handle mutable arguments. Consider cache size limits and cleanup. Used in dynamic programming, expensive computations.