Skip to content
Back to Interview Guides
Interview Guide

Top 30 Python Coding Challenges for Every Level

· 9 min read

Python Challenges for Every Career Stage

Navigating a career in software development means constantly growing your skills. Whether you’re a junior developer writing your first scripts, a mid-level engineer building complex applications, or a senior dev architecting systems, targeted Python practice is key.

That’s exactly what this page is for. We’ve organized Python coding challenges specifically for Junior, Mid-Level, and Senior developers for each level. It’s the perfect way to prepare for your next career move or to find the perfect Python programmer for your team.

Jump to Your Level

Junior Developer Mid-Level Developer Senior Developer

Junior Developer Challenges

1. Reverse a String

Tests basic string slicing.

def reverse_string(s):
  return s[::-1]

2. Check for Palindrome

A simple test of string comparison and slicing.

def is_palindrome(s):
  return s == s[::-1]

3. FizzBuzz

The quintessential test of basic loops and conditionals.

def fizz_buzz(n):
  for i in range(1, n + 1):
    if i % 15 == 0:
      print("FizzBuzz")
    elif i % 3 == 0:
      print("Fizz")
    elif i % 5 == 0:
      print("Buzz")
    else:
      print(i)

4. Find Maximum in List

A fundamental list operation.

def find_max(numbers):
  return max(numbers)

5. Sum of a List

A simple loop to practice accumulation.

def sum_list(numbers):
  return sum(numbers)

6. Count Vowels in a String

Good for practicing character-by-character string processing.

def count_vowels(s):
  vowels = "aeiou"
  return sum(1 for char in s.lower() if char in vowels)

7. Factorial of a Number

A classic introduction to recursion.

def factorial(n):
  if n <= 1:
    return 1
  return n * factorial(n - 1)

8. Find an Element in a List

Checks for understanding of basic search logic.

def find_element(elements, target):
  for i, element in enumerate(elements):
    if element == target:
      return i
  return -1

9. Check if Number is Even or Odd

Tests the most basic conditional logic.

def is_even(num):
  return num % 2 == 0

10. Concatenate Two Lists

A problem for understanding basic list operations.

def concat_lists(list_a, list_b):
  return list_a + list_b

Mid-Level Developer Challenges

1. Two Sum

The classic interview question to test knowledge of dictionaries.

def two_sum(nums, target):
  seen = {}
  for i, num in enumerate(nums):
    complement = target - num
    if complement in seen:
      return [seen[complement], i]
    seen[num] = i

2. Valid Parentheses

A perfect problem for demonstrating the use of a stack (via a list).

def is_valid_parentheses(s):
  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

3. Binary Search

Tests understanding of efficient search algorithms in a sorted list.

def binary_search(arr, target):
  left, right = 0, len(arr) - 1
  while left <= right:
    mid = (left + right) // 2
    if arr[mid] == target:
      return mid
    elif arr[mid] < target:
      left = mid + 1
    else:
      right = mid - 1
  return -1

4. Group Anagrams

Requires creative use of dictionaries and sorting to group words.

from collections import defaultdict
def group_anagrams(strs):
  anagrams = defaultdict(list)
  for s in strs:
    anagrams[tuple(sorted(s))].append(s)
  return list(anagrams.values())

5. Longest Substring Without Repeating Characters

A sliding window problem that tests dynamic substring analysis.

def length_of_longest_substring(s):
  char_set = set()
  left = 0
  max_len = 0
  for right, char in enumerate(s):
    while char in char_set:
      char_set.remove(s[left])
      left += 1
    char_set.add(char)
    max_len = max(max_len, right - left + 1)
  return max_len

6. Invert a Binary Tree

A classic recursive tree manipulation problem.

def invert_tree(root):
  if not root:
    return None
  root.left, root.right = invert_tree(root.right), invert_tree(root.left)
  return root

7. Implement a Queue using Stacks

Tests knowledge of data structure properties and how to simulate one with another.

class MyQueue:
  def __init__(self):
    self.s1 = []
    self.s2 = []
  def push(self, x):
    self.s1.append(x)
  def pop(self):
    if not self.s2:
      while self.s1:
        self.s2.append(self.s1.pop())
    return self.s2.pop()

8. Product of List Except Self

A tricky list problem that can be solved efficiently without division.

def product_except_self(nums):
  n = len(nums)
  result = [1] * n
  prefix = 1
  for i in range(n):
    result[i] = prefix
    prefix *= nums[i]
  postfix = 1
  for i in range(n - 1, -1, -1):
    result[i] *= postfix
    postfix *= nums[i]
  return result

9. Rotate a Matrix

An in-place matrix manipulation problem requiring careful indexing.

def rotate(matrix):
  n = len(matrix)
  for i in range(n): # Transpose
    for j in range(i, n):
      matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
  for i in range(n): # Reverse each row
    matrix[i].reverse()

10. First Non-Repeating Character

Requires use of a hash map or dictionary to count character frequencies.

import collections
def first_uniq_char(s):
  count = collections.Counter(s)
  for i, char in enumerate(s):
    if count[char] == 1:
      return i
  return -1

Senior Developer Challenges

1. Merge K Sorted Lists

Tests efficient merging using a min-heap from the `heapq` module.

import heapq
def merge_k_lists(lists):
  heap = [(l.val, i) for i, l in enumerate(lists) if l]
  heapq.heapify(heap)
  head = tail = ListNode(None)
  while heap:
    val, i = heapq.heappop(heap)
    tail.next = ListNode(val)
    tail = tail.next
    node = lists[i] = lists[i].next
    if node:
      heapq.heappush(heap, (node.val, i))
  return head.next

2. Trapping Rain Water

A classic problem requiring an optimal two-pointer approach.

def trap(height):
  if not height: return 0
  l, r = 0, len(height) - 1
  left_max, right_max = height[l], height[r]
  water = 0
  while l < r:
    if left_max < right_max:
      l += 1
      left_max = max(left_max, height[l])
      water += left_max - height[l]
    else:
      r -= 1
      right_max = max(right_max, height[r])
      water += right_max - height[r]
  return water

3. Word Break

A dynamic programming problem testing string segmentation.

def word_break(s, word_dict):
  word_set = set(word_dict)
  dp = [False] * (len(s) + 1)
  dp[0] = True
  for i in range(1, len(s) + 1):
    for j in range(i):
      if dp[j] and s[j:i] in word_set:
        dp[i] = True
        break
  return dp[len(s)]

4. LRU Cache

A system design problem elegantly solved with `collections.OrderedDict`.

from collections import OrderedDict
class LRUCache(OrderedDict):
  def __init__(self, capacity: int):
    self.capacity = capacity
  def get(self, key: int) -> int:
    if key not in self:
      return -1
    self.move_to_end(key)
    return self[key]
  def put(self, key: int, value: int) -> None:
    if key in self:
      self.move_to_end(key)
    self[key] = value
    if len(self) > self.capacity:
      self.popitem(last=False)

5. Find Median from Data Stream

Requires balancing two heaps to maintain the median in real-time.

import heapq
class MedianFinder:
  def __init__(self):
    self.small = [] # max-heap
    self.large = [] # min-heap
  def addNum(self, num):
    heapq.heappush(self.small, -1 * num)
    if self.small and self.large and (-1 * self.small[0]) > self.large[0]:
      val = -1 * heapq.heappop(self.small)
      heapq.heappush(self.large, val)
    if len(self.small) > len(self.large) + 1:
      val = -1 * heapq.heappop(self.small)
      heapq.heappush(self.large, val)
    if len(self.large) > len(self.small) + 1:
      val = heapq.heappop(self.large)
      heapq.heappush(self.small, -1 * val)
  def findMedian(self):
    if len(self.small) > len(self.large):
      return -1 * self.small[0]
    if len(self.large) > len(self.small):
      return self.large[0]
    return (-1 * self.small[0] + self.large[0]) / 2.0

6. Number of Islands

A graph traversal problem on a grid, typically solved with DFS or BFS.

def num_islands(grid):
  if not grid: return 0
  rows, cols = len(grid), len(grid[0])
  visited = set()
  islands = 0
  def dfs(r, c):
    if (r not in range(rows) or
        c not in range(cols) or
        grid[r][c] == '0' or (r, c) in visited):
      return
    visited.add((r, c))
    dfs(r + 1, c); dfs(r - 1, c); dfs(r, c + 1); dfs(r, c - 1)
  for r in range(rows):
    for c in range(cols):
      if grid[r][c] == '1' and (r, c) not in visited:
        dfs(r, c)
        islands += 1
  return islands

7. Longest Palindromic Substring

A dynamic programming problem or can be solved with an “expand from center” approach.

def longest_palindrome(s):
  res = ""
  res_len = 0
  for i in range(len(s)):
    # Odd length
    l, r = i, i
    while l >= 0 and r < len(s) and s[l] == s[r]:
      if (r - l + 1) > res_len:
        res = s[l:r+1]
        res_len = r - l + 1
      l -= 1; r += 1
    # Even length
    l, r = i, i + 1
    while l >= 0 and r < len(s) and s[l] == s[r]:
      if (r - l + 1) > res_len:
        res = s[l:r+1]
        res_len = r - l + 1
      l -= 1; r += 1
  return res

8. Coin Change

A classic dynamic programming problem to find the minimum number of coins for a given amount.

def coin_change(coins, amount):
  dp = [float('inf')] * (amount + 1)
  dp[0] = 0
  for coin in coins:
    for i in range(coin, amount + 1):
      dp[i] = min(dp[i], dp[i - coin] + 1)
  return dp[amount] if dp[amount] != float('inf') else -1

9. Implement Trie (Prefix Tree)

Tests knowledge of specialized tree data structures for efficient string searching.

class TrieNode:
  def __init__(self):
    self.children = {}
    self.is_end_of_word = False

class Trie:
  def __init__(self):
    self.root = TrieNode()
  def insert(self, word):
    node = self.root
    for char in word:
      if char not in node.children:
        node.children[char] = TrieNode()
      node = node.children[char]
    node.is_end_of_word = True

10. Regular Expression Matching

A highly complex dynamic programming problem involving pattern matching logic.

def is_match(s, p):
  dp = [[False] * (len(p) + 1) for _ in range(len(s) + 1)]
  dp[0][0] = True
  for j in range(1, len(p) + 1):
    if p[j-1] == '*':
      dp[0][j] = dp[0][j-2]
  for i in range(1, len(s) + 1):
    for j in range(1, len(p) + 1):
      if p[j-1] == '.' or p[j-1] == s[i-1]:
        dp[i][j] = dp[i-1][j-1]
      elif p[j-1] == '*':
        dp[i][j] = dp[i][j-2]
        if p[j-2] == s[i-1] or p[j-2] == '.':
          dp[i][j] |= dp[i-1][j]
  return dp[len(s)][len(p)]

Tips to Prepare for Python Coding Challenges

  • Master the Fundamentals: Have a strong grip on Python’s core data types (lists, tuples, dictionaries, sets) and control flow.
  • Embrace Pythonic Code: Practice using list comprehensions, generators, and built-in functions (`map`, `filter`) to write clean, efficient, and readable solutions.
  • Know Your Standard Library: Get familiar with essential modules like `collections` (especially `defaultdict`, `Counter`, `deque`), `itertools`, and `heapq`. They can drastically simplify complex problems.
  • Understand Time and Space Complexity: Be ready to discuss the complexity (Big O notation) of your solutions. This is crucial in mid-level and senior interviews.
  • Practice on a Whiteboard: Simulate real interview conditions by solving problems without an IDE. This helps you focus on the logic rather than relying on autocompletion.
  • Communicate Your Thought Process: During an interview, talk through your solution. Explain your approach, why you chose a particular data structure, and what trade-offs you’re making.

Conclusion

Every great developer was once a beginner. While these challenges might seem tough, consistent practice is the best way to build confidence and develop the problem-solving instincts needed to excel in any technical interview. Keep coding!

Skip the interview marathon.

We pre-vet senior engineers across Asia using these exact questions and more. Get matched in 24 hours, $0 upfront.

Get Pre-Vetted Talent
WhatsApp