Here is the part most prep guides skip: in a real coding interview you almost never solve these problems alone on a whiteboard. You solve them live, typing into a shared editor while an interviewer reads along in real time — watching every keystroke, every pause, every time you backtrack and rename a variable. The code matters, but so does everything around it: how you start, how you narrate, and how you recover when something breaks in front of another person.
That live, observed context is exactly what this guide keeps in view. We still walk through all five levels — beginner problems, intermediate array questions, HashMap patterns, linked list fundamentals, and a full LRU Cache deep dive — with complete code and time and space complexity for each. But we frame them the way they actually get run: as a conversation happening inside a shared session, not a silent paper exercise. Whether you are preparing for your first internship loop or targeting top tech companies, understanding both the patterns and how they read on a live screen will dramatically improve your confidence.
Where this ladder ends: the LRU cache
1 Level 1 — Beginner Problems
Beginner coding interview questions are not designed to trick you. They test whether you can understand the requirements, write syntactically correct code, use basic control flow, handle edge cases, and explain your logic. Many candidates underestimate beginner problems and fail because they rush.
Common beginner questions include FizzBuzz, palindrome checks, string reversal, finding the maximum in an array, vowel counting, prime checks, and factorials. The most famous is FizzBuzz — and it filters out more candidates than it should.
The problem. Print numbers from 1 to n. Replace multiples of 3 with Fizz, multiples of 5 with Buzz, and multiples of both with FizzBuzz.
The wrong logic most candidates write. Notice the bug — multiples of 15 are caught by the first branch before the FizzBuzz branch can ever fire.
if n % 3 == 0:
print("Fizz")
elif n % 5 == 0:
print("Buzz")
elif n % 15 == 0: # never reached
print("FizzBuzz")Correct ordering. Check the most specific condition first.
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)Time complexity O(n), space O(1). The interviewer is not impressed by a clever solution here — they are watching whether you talk through the ordering decision before you write any code.
2 Level 2 — Intermediate Array Questions
Arrays are the most important data structure in coding interviews. If beginner questions test the basics, array problems test pattern recognition, optimisation ability, and algorithmic thinking. Most interview rounds contain at least one array problem.
Popular questions include Two Sum, Best Time to Buy and Sell Stock, Maximum Subarray, Move Zeroes, Merge Intervals, Product of Array Except Self, Rotate Array, and Trapping Rain Water. They all share a hidden theme: an interviewer expects you to start with brute force and then improve.
Two Sum — brute force.
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
if nums[i] + nums[j] == target:
return [i, j]Time O(n²), space O(1). Interviewers expect candidates to improve this.
Two Sum — HashMap optimisation.
seen = {}
for i, num in enumerate(nums):
complement = target - num
if complement in seen:
return [seen[complement], i]
seen[num] = iTime O(n), space O(n). This problem introduces one of the most important interview concepts: trading space for speed.
Sliding window. Useful for continuous subarrays, fixed-size ranges, and dynamic windows. The maximum sum subarray of size k drops from O(n × k) to O(n) with one trick — instead of recomputing each window, slide it by adding the new element and removing the old one.
window_sum = sum(arr[:k])
max_sum = window_sum
for i in range(k, len(arr)):
window_sum += arr[i]
window_sum -= arr[i - k]
max_sum = max(max_sum, window_sum)Two pointers. Equally important when an array is sorted, or when checking palindromes, pair searching, or partitioning. The classic palindrome check walks two indices toward the middle.
left, right = 0, len(s) - 1
while left < right:
if s[left] != s[right]:
return False
left += 1
right -= 1
return TrueCommon mistakes in this level: off-by-one errors, ignoring empty arrays, incorrect index handling, and forgetting duplicates. Practising patterns is more valuable than memorising solutions — once you recognise “sliding window” in a problem statement, the rest writes itself.
3 Level 3 — HashMap Patterns
HashMaps are among the most powerful tools in coding interviews. Many otherwise difficult problems become easy once you spot a HashMap pattern. Average-case lookup is O(1), which means you can usually trade memory to drop one full level of time complexity.
The core patterns are frequency counting, prefix sums, fast lookup, grouping, and caching previous results. Each of those names matches a family of common problems.
Frequency counting — Valid Anagram.
from collections import Counter
return Counter(s) == Counter(t)Two strings are anagrams if their character frequencies match. Interviewers want you to explain why this works, not just that it does.
Prefix sums — Subarray Sum Equals K. Find the number of continuous subarrays summing to k. The trick: store running prefix sums and check whether prefix - k has been seen before.
count = 0
prefix_sum = 0
prefix_map = {0: 1}
for num in nums:
prefix_sum += num
if prefix_sum - k in prefix_map:
count += prefix_map[prefix_sum - k]
prefix_map[prefix_sum] = prefix_map.get(prefix_sum, 0) + 1This problem combines prefix sums, HashMap lookup, and mathematical reasoning. Variants of it appear in Google, Meta, and Amazon interviews regularly.
Grouping — Group Anagrams. Sorted characters become a stable key for any anagram family.
from collections import defaultdict
groups = defaultdict(list)
for word in strs:
key = ''.join(sorted(word))
groups[key].append(word)
return list(groups.values())Complexity O(n × k log k) where k is the average word length.
Before reaching for a HashMap, ask yourself four questions: do I need fast lookup, am I counting frequencies, do I need previous results, am I checking duplicates? Any “yes” is a strong signal a HashMap will help.
HashMap operations — insert, lookup, and delete — are all O(1) on average. Worst case becomes O(n) because of collisions, though modern implementations minimise this.
4 Level 4 — Linked List Fundamentals
Linked lists are one of the most misunderstood interview topics. Many developers rarely use them in day-to-day work, but interviewers love them because they test pointer manipulation, memory understanding, logical precision, and edge-case handling.
A linked list is a sequence of nodes, each containing data and a pointer to the next. Unlike arrays, linked lists are not stored contiguously in memory. They have dynamic size and efficient insertion/deletion, at the cost of no random access and extra memory for pointers.
Reverse a linked list — iterative. Among the most common interview questions.
prev = None
current = head
while current:
nxt = current.next
current.next = prev
prev = current
current = nxt
return prevTime O(n), space O(1). Interviewers use this problem to test pointer manipulation skills more than algorithmic creativity.
Fast and slow pointers — Floyd's cycle detection. Detect a cycle, find the middle node, validate a palindrome list — all variations of the same idea.
slow = head
fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return FalseThe fast pointer eventually catches the slow one if a cycle exists — otherwise it reaches null. Time O(n), space O(1). Knowing this algorithm by name impresses interviewers because it shows you have seen it before and understood it.
Dummy node technique. Many linked list problems become easier with a sentinel node — it removes the special case of an empty list or a deletion at the head.
dummy = ListNode(0)
dummy.next = headCommon mistakes: losing references, infinite loops, incorrect pointer updates, null-pointer exceptions, and ignoring empty lists. Draw the pointers on paper before you write code — it sounds slow, but candidates who visualise the list out loud almost always finish faster than candidates who don't.
5 Level 5 — LRU Cache Deep Dive
Now the famous one. The LRU Cache problem combines HashMaps, linked lists, and design thinking. It appears regularly at Google, Amazon, Meta, and other top-tier interviews because it is the smallest possible problem that forces a candidate to combine two data structures deliberately.
The requirement. Both get(key) and put(key, value) must run in O(1). When capacity is exceeded the least recently used item is evicted. LRU caches power browser caches, database buffer pools, operating system page caches, CDNs, and almost every memory tier in production systems.
Why arrays alone fail. Searching is O(n), deletion is O(n), and updating order is inefficient. A linked list alone solves the ordering problem but still costs O(n) to find a key. A HashMap alone solves lookup but cannot track usage order.
The optimal combination. A HashMap maps keys to nodes. A doubly linked list orders nodes from most recently used to least recently used. Every access moves the node to the front; every eviction removes from the back. Both operations are O(1).
Node and class.
class Node:
def __init__(self, key, value):
self.key = key
self.value = value
self.prev = None
self.next = None
class LRUCache:
def __init__(self, capacity):
self.capacity = capacity
self.cache = {}
# Sentinel nodes — left = LRU side, right = MRU side
self.left = Node(0, 0)
self.right = Node(0, 0)
self.left.next = self.right
self.right.prev = self.left
def remove(self, node):
prev, nxt = node.prev, node.next
prev.next, nxt.prev = nxt, prev
def insert(self, node):
# Insert just before the right sentinel (MRU end)
prev, nxt = self.right.prev, self.right
prev.next = node
node.prev = prev
node.next = nxt
nxt.prev = node
def get(self, key):
if key in self.cache:
self.remove(self.cache[key])
self.insert(self.cache[key])
return self.cache[key].value
return -1
def put(self, key, value):
if key in self.cache:
self.remove(self.cache[key])
self.cache[key] = Node(key, value)
self.insert(self.cache[key])
if len(self.cache) > self.capacity:
lru = self.left.next
self.remove(lru)
del self.cache[lru.key]Complexity: get and put are both O(1), space O(capacity).
Interview talking points. Explain why arrays fail, why linked lists alone are not enough, why the list must be doubly linked, and how the HashMap accelerates lookup. Communication here matters as much as code — even a perfect solution loses points when the candidate cannot articulate the trade-offs.
Frequent mistakes. Forgetting to update pointers, removing the wrong node, breaking the chain when the list has one item, mishandling duplicate keys in put, and forgetting to remove the evicted entry from the HashMap when the list pops it.
6 Complexity, Big O, and Why It Always Comes Up
Understanding complexity is essential at every interview level. The question “can this be optimised?” comes up in almost every coding round, and confident Big-O analysis distinguishes candidates more than any single solved problem.
O(1) constant — HashMap lookup
O(log n) logarithmic — binary search
O(n) linear — single-pass loop
O(n log n) efficient sort — merge sort, quicksort
O(n²) nested loops — naive Two Sum
O(2^n) exponential — naive recursionA solution that runs in O(n²) handles ten items fine and times out on ten million. Optimised to O(n), the same code handles massive datasets — and that jump usually requires only the introduction of a HashMap or a sliding window.
Don't ignore space complexity. Recursive solutions use stack space, HashMaps trade memory for speed, and large auxiliary arrays consume RAM. The interviewer wants you to name the trade-off, not pretend it doesn't exist.
7 What Interviewers Actually Evaluate
Coding interviews evaluate problem-solving approach, communication, optimisation ability, debugging skills, confidence, and collaboration. Strong candidates follow a predictable rhythm.
- Clarify the problem before writing code.
- State the brute-force approach out loud.
- Analyse the brute-force complexity.
- Optimise gradually, narrating the reasoning.
- Test the solution against edge cases.
The most common candidate mistakes. Jumping into code too quickly leads to incorrect assumptions and silent bugs. Ignoring edge cases — empty arrays, single elements, duplicates, negatives — is the single biggest reason interviewers downgrade an otherwise solid round. And silent candidates create uncertainty: interviewers cannot give partial credit for thinking they cannot see.
8 How to Practise Effectively
Do not memorise hundreds of solutions. Memorise patterns — sliding window, two pointers, HashMaps, BFS/DFS, dynamic programming, and greedy algorithms. Patterns transfer across problems in a way that individual solutions never will.
Build interview stamina with timed sessions, whiteboard or shared-editor coding, and mock interviews where you explain aloud. Real interviews are stressful precisely because you must perform while you think — and that performance habit is built through repetition.
A reasonable progression: variables and loops → arrays, strings, HashMaps → linked lists, stacks, queues, trees, graphs → recursion, backtracking, dynamic programming, basic system design. Each layer reuses the layer below it, which is exactly why this article was structured the same way.
If you are practising with a friend, paste your code into a ShareCode editor and walk through it together — the conversation is usually where the real learning happens. When we run mock interviews in ShareCode, the LRU Cache problem is the one where talking through the doubly-linked-list pointer updates out loud — while your partner watches your cursor move in real time — catches more bugs than staring at the code alone ever does. We also wrote a longer companion piece on conducting technical interviews online if you are on the hiring side of the table.
Solving These Live: What the Interviewer Actually Watches
Every problem above changes character the moment it's solved in front of someone. In a real round the interviewer isn't grading a finished file — they're reading a shared session as it unfolds. The first signal they pick up is how you start: do you ask clarifying questions (“can the input array be empty? are keys unique?”) or dive straight into typing? Both can be fine, but the candidates who pause to restate the problem in their own words almost always look more in control five minutes later. The second signal is narration. When your cursor is visible and you go quiet for ninety seconds, the interviewer has no idea whether you're stuck or thinking — so they can't give partial credit for reasoning they can't see.
Watch what happens when they drop a hint directly into the file — a comment like # what if capacity is 0? appearing under your cursor. How you react to that is itself being evaluated: do you acknowledge it, fold it into your approach, and keep going, or do you ignore it and barrel toward a broken solution? The same is true when a test case fails in real time. Re-running and silently retyping reads very differently from saying “okay, this fails on the single-node list — that means my remove is breaking the chain, let me trace the pointers.”
A few practical habits help on both sides of a live shared editor. Pre-load the prompt as a comment block at the top so the candidate and interviewer are literally reading the same words. Talk through the LRU Cache pointer updates as you type them — prev.next = nxt, then nxt.prev = prev — because the doubly-linked-list rewiring is exactly where silent candidates lose people. And keep your names clear: lru beats n2 when someone is reading along character by character.
This is the exact use case we built ShareCode for. The candidate joins by URL — no install, no signup — and from that moment both people see the same editor, the same cursors, and the same keystrokes as they happen. The interview stops being a guess about what someone would write and becomes a recording of how they actually think, hint by hint and fix by fix.
Frequently Asked Questions
- Why do interviewers still ask FizzBuzz in 2026?
- FizzBuzz is not designed to be hard. It is designed to filter out candidates who cannot translate a written specification into working code under mild pressure. Interviewers also watch how you order the conditions, whether you check the divisible-by-15 case first, and how clearly you talk through the loop — all signals that scale to harder problems.
- What is the most important data structure for coding interviews?
- Arrays and HashMaps. Most intermediate questions reduce to iterating an array once while using a HashMap to remember what you have already seen — Two Sum, Subarray Sum Equals K, Group Anagrams, and Longest Consecutive Sequence are all variations of that single pattern.
- Why does an LRU Cache need both a HashMap and a doubly linked list?
- The HashMap gives
O(1)lookup by key. The doubly linked list givesO(1)insertion, deletion, and node-moving so you can update the usage order without scanning. Either structure on its own forces at least one operation toO(n)— together they hit the constraint for bothgetandput. - How do I detect a cycle in a linked list?
- Use Floyd's tortoise-and-hare algorithm. Move a slow pointer one step at a time and a fast pointer two steps. If the list has a cycle the fast pointer will eventually lap the slow pointer and they will meet. If the fast pointer reaches
null, there is no cycle. TimeO(n), spaceO(1). - What do interviewers actually evaluate during a coding interview?
- Roughly four things: whether you clarify the problem before coding, whether you can articulate a brute-force solution and then improve it, whether your code handles edge cases (empty input, duplicates, single element), and whether you communicate trade-offs. Silent candidates who write perfect code often score lower than candidates who narrate a reasonable solution.
About the author — Kajal Pansuriya
Kajal is a software engineer who has sat through more than fifty technical interview loops on both sides of the table. She writes interview-prep guides for the ShareCode blog. Every problem and complexity analysis in this article was pulled from real rounds at product companies across India and the US.
Final Thoughts
The journey from FizzBuzz to LRU Cache mirrors the evolution of a software engineer's thinking. At first, interview questions feel like isolated puzzles. Eventually you start seeing the patterns — arrays teach iteration, HashMaps teach optimisation, linked lists teach pointer logic, and the LRU Cache teaches system design thinking inside a single function.
You do not need to solve the hardest problems first. Build strong fundamentals, learn patterns deeply, practise explaining solutions out loud, and review mistakes carefully. A candidate who clearly communicates a reasonable solution almost always outperforms a silent candidate writing complex code. The path is not really about algorithms — it is about learning to think like an engineer.
References & Sources
The primary sources, specifications, and documentation behind this article. Each link opens in a new tab.
- functools — @functools.lru_cache
Python Software Foundation · Python 3 Standard Library documentation
The canonical least-recently-used cache decorator in Python, with the maxsize eviction behaviour discussed in the LRU Cache section.
docs.python.org - collections — OrderedDict and move_to_end()
Python Software Foundation · Python 3 Standard Library documentation
Documents the ordered-mapping primitive the docs explicitly recommend for implementing LRU caches — the std-lib analogue of the HashMap + doubly linked list design.
docs.python.org - Map
MDN Web Docs · Mozilla
Reference for the JavaScript hash-map analogue used in the HashMap-pattern problems; the spec requires sublinear (typically O(1)) lookup.
developer.mozilla.org - Cycle detection — Floyd's tortoise and hare algorithm
Wikipedia contributors · Wikipedia
Background on the O(1)-space fast/slow pointer technique used in the linked-list cycle-detection section.
en.wikipedia.org
About the writers
Developer educator at ShareCode. Writes the tutorial track — Python, JavaScript debugging, coding-interview prep, and the everyday code-quality habits that hold up in real codebases.
More from Kajal
Founder of ShareCode. Writes the engineering deep-dives on this site — WebRTC, Firebase Auth, real-time sync, and the production patterns behind the editor itself.
More from Kishan
Practise coding interviews in a shared editor
Open a ShareCode editor, paste any problem from this guide, and send the URL to a study partner. Real-time cursors, no installs, free forever.
Open a practice code space →