Cracking ML Interviews

Open in the interactive study hub

Python Coding Challenges for Interviews

This guide focuses on the Python coding rounds that appear in ML engineer, AI engineer, data engineer, and backend-leaning interviews.

The goal is not competitive programming for its own sake. The goal is to get fast and reliable at the patterns that show up in real interview loops.


What Interviewers Usually Test


1. Arrays, Strings, and Hash Maps

Concepts to know

Typical prompts

Example: top-k frequent elements

from collections import Counter
import heapq

def top_k_frequent(nums: list[int], k: int) -> list[int]:
    counts = Counter(nums)
    return [value for value, _ in heapq.nlargest(k, counts.items(), key=lambda x: x[1])]

Why it matters

This pattern appears in:


2. Two Pointers and Sliding Window

Concepts to know

Typical prompts

Example: longest substring without repeating characters

def longest_unique_substring(s: str) -> int:
    seen = {}
    left = 0
    best = 0

    for right, ch in enumerate(s):
        if ch in seen and seen[ch] >= left:
            left = seen[ch] + 1
        seen[ch] = right
        best = max(best, right - left + 1)

    return best

Why it matters

This is useful for:


3. Sorting, Intervals, and Heaps

Concepts to know

Typical prompts

Example: merge intervals

def merge_intervals(intervals: list[list[int]]) -> list[list[int]]:
    if not intervals:
        return []

    intervals = sorted(intervals, key=lambda x: x[0])   # don't reorder the caller's list
    merged = [list(intervals[0])]                        # copy, so merging never mutates the input

    for start, end in intervals[1:]:
        last = merged[-1]
        if start <= last[1]:
            last[1] = max(last[1], end)
        else:
            merged.append([start, end])

    return merged

Why it matters

The same reasoning appears in:


4. Stack and Queue Patterns

Concepts to know

Typical prompts

Example: valid parentheses

def is_valid_parentheses(s: str) -> bool:
    pairs = {")": "(", "]": "[", "}": "{"}
    stack = []

    for ch in s:
        if ch in pairs.values():
            stack.append(ch)
        elif ch in pairs:
            if not stack or stack.pop() != pairs[ch]:
                return False

    return not stack

Why it matters

These patterns show up in:


5. Trees and Graphs

Concepts to know

Typical prompts

Example: topological sort for dependencies

from collections import defaultdict, deque

def topo_sort(edges: list[tuple[str, str]]) -> list[str]:
    graph = defaultdict(list)
    indegree = defaultdict(int)
    nodes = set()

    for src, dst in edges:
        graph[src].append(dst)
        indegree[dst] += 1
        nodes.add(src)
        nodes.add(dst)

    q = deque([node for node in nodes if indegree[node] == 0])
    order = []

    while q:
        node = q.popleft()
        order.append(node)
        for nxt in graph[node]:
            indegree[nxt] -= 1
            if indegree[nxt] == 0:
                q.append(nxt)

    return order if len(order) == len(nodes) else []

Why it matters

Graph problems map directly to:

Related repo reading:


Concepts to know

Typical prompts

Example: first index greater than or equal to target

def lower_bound(nums: list[int], target: int) -> int:
    left, right = 0, len(nums)

    while left < right:
        mid = (left + right) // 2
        if nums[mid] < target:
            left = mid + 1
        else:
            right = mid

    return left

Why it matters

This pattern appears in:


7. Dynamic Programming Basics

Concepts to know

Typical prompts

Example: coin change

def coin_change(coins: list[int], amount: int) -> int:
    dp = [amount + 1] * (amount + 1)
    dp[0] = 0

    for value in range(1, amount + 1):
        for coin in coins:
            if coin <= value:
                dp[value] = min(dp[value], dp[value - coin] + 1)

    return dp[amount] if dp[amount] <= amount else -1

Why it matters

Even if the exact DP problem never appears in production code, it tests whether you can define state cleanly and reason about optimization.


8. Matrix and Tabular Operations

Concepts to know

Typical prompts

Example: chunk records for batch inference

def batch_items(items: list[dict], batch_size: int) -> list[list[dict]]:
    return [items[i:i + batch_size] for i in range(0, len(items), batch_size)]

Why it matters

This appears constantly in:

Related repo reading:


Practice Checklist

Easy

Medium

Harder but high value


What to Say in the Interview

For each Python problem:

  1. State the brute-force idea first if it helps anchor the problem.
  2. State the target complexity.
  3. Choose the core structure: hash map, heap, deque, recursion, or graph.
  4. Walk through one sample input.
  5. Call out edge cases:
    • empty input
    • duplicates
    • negative values
    • single element
    • disconnected graph

Common Mistakes


Repo Concepts to Pair With Practice

If you can solve medium Python problems and explain the linked concepts cleanly, you will cover a large share of ML and AI coding rounds.

View or edit this guide on GitHub