Back to blog
Interview Prep11 min read

Real Graduate Coding Tests from UK Companies - With Full Walkthroughs (2026)

Actual coding test questions from UK graduate scheme and tech job assessments - with difficulty ratings, worked solutions, and the thought process you need to solve them under time pressure.

Why Generic LeetCode Practice Isn't Enough

Most coding interview prep advice tells you to grind LeetCode. What it doesn't tell you is that UK graduate coding tests have specific formats, common question types, and recurring themes that are quite different from grinding random problems. The graduates who perform best know what to expect before they open the test window.

This guide covers real question types from UK graduate coding assessments - the HackerRank and Codility tests used by companies across the UK tech sector - with full solution walkthroughs and the thought process you need to apply under time pressure. For structured prep, also read our 30-day coding interview preparation guide.

The Formats: What UK Companies Actually Use

Before looking at specific questions, understand the three formats you'll encounter:

  • HackerRank: Used by Goldman Sachs, JP Morgan, Amazon, and many mid-market employers. Timed (usually 90 minutes for 3-4 problems). Auto-graded against test cases. You can use any language.
  • Codility: Used by Barclays, BT, Capgemini, and many UK scale-ups. Similar format to HackerRank. Often includes a "candidate report" section where you explain your approach. Green/yellow/red task completion feedback after submission.
  • CoderPad (live): Used for technical phone screens at Google, Meta, Palantir. You code in a shared editor while the interviewer watches. Talking through your thinking is as important as the solution.
  • Custom platforms: Some companies (Wise, Monzo) build their own technical assessment. Usually similar to HackerRank in structure.

Question Type 1 - String Manipulation (Difficulty: Easy-Medium)

Real question style: "Validate a UK National Insurance Number"

Seen in: UK financial services graduate assessments (Barclays, HSBC, insurance tech companies)

The problem: Write a function that validates whether a given string is a valid UK National Insurance Number. A valid NI number follows the format: two letters, six digits, one letter (e.g., AB123456C). The first letter cannot be D, F, I, Q, U, or V. The second letter cannot be D, F, I, O, Q, U, or V. The final letter must be A, B, C, or D.

Why this question appears in finance tech assessments: It mirrors real-world data validation problems these companies deal with constantly. It tests regex knowledge, edge case thinking, and understanding of constraints - without requiring complex algorithms.

Walkthrough - Step 1: Clarify the requirements

Before coding: "Is the input always a string? Can it contain spaces (NI numbers are sometimes written with spaces)? Should the validation be case-insensitive?" These clarifications would matter in a live interview and are good habits even in a timed test.

Walkthrough - Step 2: Approach

Regex is the right tool here. The pattern: ^[A-CEGHJ-PR-TW-Z][A-CEGHJ-NPR-TW-Z]d{6}[A-D]$. The character exclusions make this slightly non-trivial - use a character class that explicitly excludes the forbidden letters.

Python solution:

import re

def validate_ni_number(ni: str) -> bool:
    # Remove spaces and convert to uppercase for normalisation
    ni = ni.replace(" ", "").upper()
    pattern = r"^[A-CEGHJ-PR-TW-Z][A-CEGHJ-NPR-TW-Z]d{6}[A-D]$"
    return bool(re.match(pattern, ni))

Key insight: Handle normalisation (spaces, case) before pattern matching. This is what separates a "works on happy path" solution from a production-quality one.

Question Type 2 - Array / Sliding Window (Difficulty: Medium)

Real question style: "Maximum Subarray Sum of Size K"

Seen in: Amazon, Wise, and most HackerRank-based graduate assessments as a warm-up problem

The problem: Given an array of integers and a number K, find the maximum sum of any contiguous subarray of size K.

Brute force approach (O(n*k)): For each starting index, sum the next K elements. This exceeds time limits for large inputs and is the approach most candidates submit in panic.

Optimal approach - Sliding Window (O(n)):

Maintain a window of size K. When you slide the window right by one position, you add the new element and remove the leftmost element. You never re-compute the full sum.

def max_subarray_sum_k(arr: list[int], k: int) -> int:
    if len(arr) < k:
        return 0

    # Compute the first window
    window_sum = sum(arr[:k])
    max_sum = window_sum

    # Slide the window
    for i in range(k, len(arr)):
        window_sum += arr[i] - arr[i - k]
        max_sum = max(max_sum, window_sum)

    return max_sum

Time complexity: O(n). Space complexity: O(1).

The insight to state out loud (in a live interview) or in comments (in a timed test): "The naive approach recomputes the sum from scratch for each window - O(n*k). The sliding window avoids this by observing that consecutive windows differ by only one element added and one removed."

Question Type 3 - HashMap / Frequency Counting (Difficulty: Medium)

Real question style: "First Non-Repeating Character"

Seen in: Goldman Sachs HackerRank assessment, HSBC Technology graduate test

The problem: Given a string, find the first character that appears exactly once. Return its index, or -1 if no such character exists.

Approach: Two passes. First pass: build a frequency map. Second pass: find the first character with frequency 1.

def first_unique_char(s: str) -> int:
    freq = {}
    for char in s:
        freq[char] = freq.get(char, 0) + 1

    for i, char in enumerate(s):
        if freq[char] == 1:
            return i

    return -1

Follow-up question (commonly asked in live versions): "How would you solve this in one pass?" Answer: Use an OrderedDict or maintain insertion order - Python 3.7+ dicts preserve insertion order, so you can update frequency while tracking first occurrence index.

Question Type 4 - Trees / Recursion (Difficulty: Medium-Hard)

Real question style: "Validate a Binary Search Tree"

Seen in: Amazon technical screen, Palantir, and most Tier 1 tech companies' graduate assessments

The problem: Given the root of a binary tree, determine if it is a valid BST (all left subtree values are less than the node, all right subtree values are greater, and this applies recursively).

Common mistake: Only checking that left child is less than parent and right child is greater. This misses cases where a right subtree node is less than an ancestor.

Correct approach: Pass min and max bounds down the recursion.

def is_valid_bst(root, min_val=float('-inf'), max_val=float('inf')) -> bool:
    if root is None:
        return True
    if root.val <= min_val or root.val >= max_val:
        return False
    return (is_valid_bst(root.left, min_val, root.val) and
            is_valid_bst(root.right, root.val, max_val))

The key insight to articulate: "The constraint isn't just 'left child is less than parent' - it's 'every node in the left subtree is less than every ancestor above it.' Passing bounds down the recursion enforces this globally, not just locally."

Question Type 5 - Dynamic Programming (Difficulty: Hard)

Real question style: "Minimum Cost Path"

Seen in: Goldman Sachs, Citadel, and quant-adjacent employers

The problem: Given a 2D grid of non-negative integers, find the path from the top-left to the bottom-right that minimises the sum of values along the path. You can only move right or down.

def min_cost_path(grid: list[list[int]]) -> int:
    m, n = len(grid), len(grid[0])
    dp = [[0] * n for _ in range(m)]
    dp[0][0] = grid[0][0]

    # Fill first row
    for j in range(1, n):
        dp[0][j] = dp[0][j-1] + grid[0][j]

    # Fill first column
    for i in range(1, m):
        dp[i][0] = dp[i-1][0] + grid[i][0]

    # Fill rest
    for i in range(1, m):
        for j in range(1, n):
            dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1])

    return dp[m-1][n-1]

Space optimisation follow-up: The above uses O(m*n) space. You can reduce to O(n) by only keeping the current and previous rows, since each cell only depends on the cell above and the cell to the left.

Time Management Strategy for Timed Tests

In a 90-minute, 3-question HackerRank test:

  • Read all questions first (5 minutes). Identify which is Easy, Medium, and Hard. Start with the easiest.
  • Allocate 20 minutes to the easy question, 35 minutes to the medium, and 30 minutes to the hard. Leave 5 minutes for review.
  • Submit a working brute-force solution before optimising. Partial credit for passing some test cases is better than no submission. Then optimise if time allows.
  • Read the constraints carefully. Input size tells you the expected time complexity. n up to 10^6 means you need O(n log n) or better. n up to 10^3 means O(n²) is probably fine.

Company-Specific Preparation

The question types above are representative but general. The most effective preparation is company-specific. GradSignal's interview playbooks include the actual question patterns, difficulty levels, and stage-by-stage breakdowns for UK graduate coding tests at specific companies - so you know whether to expect sliding window problems or dynamic programming before you open the test. Create a free account to access them.

Find your next graduate tech role

GradSignal lists UK graduate tech jobs alongside company-specific interview playbooks - so you can apply and prepare in one place.