Skip to content
Laviyx Learn

Try

Python course menu

Python Coding Challenges With Solutions (Interview Practice)

Ten classic Python coding interview challenges with hints and tested solutions: two sum, anagrams, first unique character, valid brackets, merging sorted lists, binary search, maximum subarray, grouping anagrams, string compression and list rotation.

Intermediate10 min readUpdated
On this page

These are classic problems from coding interviews and online assessments. Each one teaches a reusable technique, such as hashing, stacks, two pointers or running totals. Try each for at least 10 minutes before opening the hint, and state the time complexity of your answer, because interviewers always ask.

Challenge 1: Two Sum#

Two Sum

Return the indexes of the two numbers in a list that add up to a target, or None if there are none. Example: [2, 7, 11, 15], target 9 → [0, 1].

Show hint

For each number, the partner you need is target - n. A dictionary of values you have already seen answers "have I seen it?" instantly.

Show solution
Python
def two_sum(nums, target):
    seen = {}                       # value -> index
    for i, n in enumerate(nums):
        if target - n in seen:
            return [seen[target - n], i]
        seen[n] = i
    return None

print(two_sum([2, 7, 11, 15], 9), two_sum([3, 2, 4], 6), two_sum([1, 2], 10))
Output
[0, 1] [1, 2] None

O(n) time, O(n) memory. The brute-force nested loop is O(n²).

Challenge 2: Anagram check#

Anagrams

Return True if two strings are anagrams (same letters, same counts), ignoring spaces and case.

Show hint

Count the letters of each string with Counter, or compare the sorted letters.

Show solution
Python
from collections import Counter

def is_anagram(a, b):
    clean = lambda s: Counter(s.replace(" ", "").lower())
    return clean(a) == clean(b)

print(is_anagram("Listen", "Silent"),
      is_anagram("Dormitory", "dirty room"),
      is_anagram("abc", "abd"))
Output
True True False

O(n) with Counter; O(n log n) with sorted().

Challenge 3: First unique character#

First unique character

Return the first character that appears exactly once in a string, or None.

Show hint

Count first, then scan the string a second time in order.

Show solution
Python
from collections import Counter

def first_unique(s):
    counts = Counter(s)
    for ch in s:
        if counts[ch] == 1:
            return ch
    return None

print(first_unique("swiss"), first_unique("aabb"), first_unique("leetcode"))
Output
w None l

Two passes, O(n) time.

Challenge 4: Valid brackets#

Valid brackets

Return True if every bracket in a string like "([]{})" is closed by the right type, in the right order.

Show hint

Use a stack: push opening brackets; on a closing bracket, the top of the stack must be its matching opener.

Show solution
Python
def is_valid(brackets):
    pairs = {")": "(", "]": "[", "}": "{"}
    stack = []
    for ch in brackets:
        if ch in "([{":
            stack.append(ch)
        elif ch in pairs:
            if not stack or stack.pop() != pairs[ch]:
                return False
    return not stack

print(is_valid("([]{})"), is_valid("([)]"), is_valid("(("), is_valid(""))
Output
True False False True

"((" fails because the stack is not empty at the end. O(n).

Challenge 5: Merge two sorted lists#

Merge sorted lists

Merge two sorted lists into one sorted list without calling sorted().

Show hint

Two pointers: repeatedly take the smaller front element, then append whatever remains.

Show solution
Python
def merge_sorted(a, b):
    i = j = 0
    out = []
    while i < len(a) and j < len(b):
        if a[i] <= b[j]:
            out.append(a[i]); i += 1
        else:
            out.append(b[j]); j += 1
    return out + a[i:] + b[j:]

print(merge_sorted([1, 4, 7], [2, 3, 8, 9]))
Output
[1, 2, 3, 4, 7, 8, 9]

O(n + m). This is the core step of merge sort.

Binary search

Find the index of a target in a sorted list in O(log n) time, or return -1.

Show hint

Keep a lo and hi range. Check the middle; discard the half that cannot contain the target.

Show solution
Python
def binary_search(items, target):
    lo, hi = 0, len(items) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if items[mid] == target:
            return mid
        if items[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1

data = [3, 8, 15, 23, 42, 57, 91]
print(binary_search(data, 42), binary_search(data, 5))
Output
4 -1

Each step halves the range: about 20 steps for a million items. The standard library's bisect module provides this too.

Challenge 7: Maximum subarray sum#

Maximum subarray

Find the largest sum of any contiguous part of a list. Example: [-2, 1, -3, 4, -1, 2, 1, -5, 4] → 6 (from [4, -1, 2, 1]).

Show hint

Kadane's algorithm: at each number, either extend the current run or start a new one, whichever is larger. Track the best seen.

Show solution
Python
def max_subarray(nums):
    best = cur = nums[0]
    for n in nums[1:]:
        cur = max(n, cur + n)
        best = max(best, cur)
    return best

print(max_subarray([-2, 1, -3, 4, -1, 2, 1, -5, 4]), max_subarray([-3, -1, -2]))
Output
6 -1

Starting from nums[0] (not 0) handles all-negative lists correctly. O(n).

Challenge 8: Group anagrams#

Group anagrams

Group words that are anagrams of each other: ["eat", "tea", "tan", "ate", "nat", "bat"].

Show hint

Anagrams have the same sorted letters. Use that as a dictionary key.

Show solution
Python
from collections import defaultdict

def group_anagrams(words):
    groups = defaultdict(list)
    for w in words:
        groups["".join(sorted(w))].append(w)
    return list(groups.values())

print(group_anagrams(["eat", "tea", "tan", "ate", "nat", "bat"]))
Output
[['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']]

O(n · k log k), where k is the word length.

Challenge 9: String compression#

String compression

Compress runs of repeated characters: "aaabccdddd" → "a3b1c2d4". An empty string stays empty.

Show hint

Walk through pairs of neighbouring characters with zip(s, s[1:]), counting until the character changes.

Show solution
Python
def compress(s):
    if not s:
        return ""
    out = []
    count = 1
    for prev, ch in zip(s, s[1:]):
        if ch == prev:
            count += 1
        else:
            out.append(f"{prev}{count}")
            count = 1
    out.append(f"{s[-1]}{count}")
    return "".join(out)

print(compress("aaabccdddd"), compress("abc"), repr(compress("")))
Output
a3b1c2d4 a1b1c1 ''

Building a list and joining once is faster than repeated string +=.

Challenge 10: Rotate a list#

Rotate a list

Rotate a list to the right by k steps: [1, 2, 3, 4, 5], k = 2 → [4, 5, 1, 2, 3]. k may be larger than the list.

Show hint

Reduce k with k % len(nums), then join two slices.

Show solution
Python
def rotate(nums, k):
    k %= len(nums)
    return nums[-k:] + nums[:-k] if k else nums[:]

print(rotate([1, 2, 3, 4, 5], 2), rotate([1, 2, 3], 4), rotate([1, 2], 0))
Output
[4, 5, 1, 2, 3] [3, 1, 2] [1, 2]

The if k guard matters: with k = 0, nums[-0:] is the whole list, which would duplicate it.

How to approach any coding challenge#

  1. Clarify: input sizes, duplicates, negative numbers, empty input.
  2. Start simple: describe a brute-force solution and its complexity.
  3. Improve: can a dictionary, set, stack, sorting, or two pointers remove a nested loop?
  4. Code cleanly: good names, small helper functions.
  5. Test out loud with a normal case and an edge case.

More practice: the Python practice sets and the programming fundamentals questions.

Finished this lesson?