Computer Notes/Python/Python Interview Cheat Sheet
High-Yield Python Patterns for Technical Interviews
1. Array (List) Iteration
Forget standard while loops or range(len(arr)) unless you specifically only need the index. Python has built-in ways to make this much cleaner and less prone to off-by-one errors.
The Enumerate Pattern (Crucial)
Whenever you need both the index and the value, always use enumerate. It shows operational maturity.
nums = [10, 20, 30] for i, num in enumerate(nums): print(f"Index: {i}, Value: {num}")
List Comprehensions
Use these for filtering or transforming data quickly. It saves space and looks highly professional.
- Create a list of squares for even numbers only
nums = [1, 2, 3, 4, 5] evens_squared = [x2 for x in nums if x % 2 == 0]
Two-Pointer Setup
Very common for array manipulation and palindrome checks.
left, right = 0, len(nums) - 1 while left < right:
- Do logic, then converge
left += 1 right -= 1
2. String Manipulation
Remember: Strings in Python are immutable. You cannot do s[0] = 'a'. You must build a new string or convert it to a list of characters first.
Splitting and Joining
This is bread-and-butter for parsing messy log files or URIs.
- Splitting a messy log line
log = "ERROR User login failed" parts = log.split() # Splits by any whitespace, stripping extras
- Rebuilding a string from a list
chars = ['G', 'o', 'o', 'g', 'l', 'e'] word = "".join(chars)
Reversing a String
Do not write a loop to reverse a string unless explicitly asked to. Use slicing.
s = "security" reversed_s = s[::-1] # "ytiruces"
Character Math (ASCII)
Crucial for encryption/decryption basics or mapping characters to an array index.
- Convert char to ASCII int, and vice versa
val = ord('a') # 97 char = chr(97) # 'a'
- Map 'a'-'z' to 0-25
index = ord('c') - ord('a') # 2
3. Linked Lists
You will almost always have to write the boilerplate class yourself if the platform doesn't provide it. Memorize this exact structure.
The Node Class
class ListNode: def **init**(self, val=0, next=None): self.val = val self.next = next
The "Dummy Node" Pattern
When doing Linked List insertions or deletions, always use a dummy node pointing to the head. It eliminates 90% of the edge cases regarding empty lists or modifying the very first node.
def process_list(head): dummy = ListNode(0) dummy.next = head curr = dummy
``` while curr.next:
if curr.next.val == "target":
# Skip the node (Deletion)
curr.next = curr.next.next
else:
curr = curr.next
return dummy.next # Returns the real, potentially modified head
```
4. The "No-IDE" Cheat Codes (Collections)
Google interviewers expect you to use Python's standard library. Import these at the top of the file; it prevents you from reinventing the wheel.
Counters (Frequency Maps)
from collections import Counter
- Instantly counts occurrences
freq = Counter(['apple', 'apple', 'orange'])
- freq = {'apple': 2, 'orange': 1}
- Get top N most frequent items (great for finding IP log spammers)
top_two = freq.most_common(2)
DefaultDict
Saves you from writing if key not in my_dict: my_dict[key] = [] a hundred times.
from collections import defaultdict
- Automatically initializes missing keys with an empty list
adj_list = defaultdict(list) adj_list['node_A'].append('node_B')
Deque (Double-Ended Queue)
If you need to pop from the left side of a list (queue.pop(0)), it takes $O(n)$ time and is a major red flag. Use a deque for $O(1)$ appends and pops on both ends.
from collections import deque queue = deque([1, 2, 3]) queue.append(4) # Adds to right queue.popleft() # Removes from left in O(1) time
5. Sorting and Lambdas (NEW)
In security engineering loops, you are frequently asked to sort complex data structures (e.g., sorting logs by timestamp, or users by privilege level).
Custom Sort Keys
Use lambda functions to sort tuples or dictionaries easily.
logs = [("10.0.0.1", 500), ("192.168.1.1", 200), ("10.0.0.2", 403)]
- Sort by the second item in the tuple (the HTTP status code)
logs.sort(key=lambda x: x[1])
- Sort in reverse (descending)
logs.sort(key=lambda x: x[1], reverse=True)
6. Graph & Tree Representation (NEW)
Security architecture heavily relies on trees (directory structures, IAM permissions) and graphs (network topologies, lateral movement).
Adjacency List for Graphs
The standard way to represent a network. Combine this with the deque for a flawless Breadth-First Search (BFS).
from collections import defaultdict, deque
- Build the graph
edges = [("A", "B"), ("A", "C"), ("B", "D")] graph = defaultdict(list) for u, v in edges: graph[u].append(v) graph[v].append(u) # Omit this line if the graph is directed
- Standard BFS Traversal
def bfs(start_node): visited = set([start_node]) queue = deque([start_node])
``` while queue:
node = queue.popleft()
print(f"Processing {node}")
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
```
7. Critical Python Gotchas (NEW)
Avoid these traps on a whiteboard; interviewers specifically watch for them.
The Mutable Default Argument Trap
Never use a list or dictionary as a default argument in a function. It evaluates once at definition time, meaning subsequent calls will share the same list memory.
- BAD:
def add_to_list(val, my_list=[]): my_list.append(val) return my_list
- GOOD:
def add_to_list(val, my_list=None): if my_list is None: my_list = [] my_list.append(val) return my_list
Initializing Min/Max Values
When you need to find a minimum or maximum value by iterating, do not initialize your tracker to 0 or 999999. Use Python's built-in infinity.
max_val = float('-inf') min_val = float('inf')