Data structures in interviews
Interviewers look for three things: choosing the right structure, writing correct code, and stating the time and space complexity. Talk through your approach before coding.
- Linear structuresArrays, linked lists, stacks and queues.
- Classic problemsReverse a list, detect a cycle, balanced brackets, two sum.
- ComplexityBig-O for time and space on every answer.
Arrays, Linked Lists, Stacks and Queues
Data structures are the core of technical interviews at product companies and an important part of service-company interviews too. This set covers the linear data structures and the classic problems built on them. Try each problem yourself before reading the code.
1. What is the difference between an array and a linked list?
An array stores elements in contiguous memory, so access by index is O(1), but inserting or deleting in the middle is O(n) because elements shift. A linked list stores nodes anywhere in memory, each pointing to the next; insertion and deletion at a known node are O(1), but finding the i-th element is O(n). Arrays are also more cache-friendly, which matters in practice.
2. What is Big-O notation?
Big-O describes how an algorithm’s time or memory grows as the input size grows, ignoring constants. Common orders: O(1) constant, O(log n) binary search, O(n) a single loop, O(n log n) efficient sorting, O(n²) nested loops. Interviewers expect you to state the complexity of every solution you write.
3. Reverse a singly linked list.
Walk through the list and reverse each next pointer, keeping track of the previous node. O(n) time, O(1) extra space.
Node reverse(Node head) {
Node prev = null, curr = head;
while (curr != null) {
Node next = curr.next; // remember the rest
curr.next = prev; // reverse the link
prev = curr;
curr = next;
}
return prev; // new head
}4. How do you detect a cycle in a linked list?
Use Floyd’s algorithm: move one pointer one step and another two steps at a time. If there is a cycle, they eventually meet; if the fast pointer reaches null, there is none. O(n) time, O(1) space.
boolean hasCycle(Node head) {
Node slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) return true;
}
return false;
}5. What are stacks and queues? Give real uses.
A stack is Last-In-First-Out: push and pop from the top. Uses: undo, browser back button, function calls, expression evaluation. A queue is First-In-First-Out: add at the rear, remove from the front. Uses: printer jobs, task scheduling, breadth-first search. In Java, ArrayDeque works well as both.
6. Check whether brackets in a string are balanced.
Push every opening bracket onto a stack. For each closing bracket, the top of the stack must be the matching opening bracket. At the end the stack must be empty. O(n) time.
boolean balanced(String s) {
Deque<Character> st = new ArrayDeque<>();
for (char c : s.toCharArray()) {
if (c == '(' || c == '[' || c == '{') st.push(c);
else if (c == ')' || c == ']' || c == '}') {
if (st.isEmpty()) return false;
char o = st.pop();
if ((c == ')' && o != '(') || (c == ']' && o != '[') || (c == '}' && o != '{')) return false;
}
}
return st.isEmpty();
}7. Implement a queue using two stacks.
Push new elements onto an “in” stack. To dequeue, if the “out” stack is empty, move everything from “in” to “out” (which reverses the order), then pop from “out”. Each element moves at most once, so operations are O(1) amortised.
class MyQueue {
private Deque<Integer> in = new ArrayDeque<>(), out = new ArrayDeque<>();
void add(int x) { in.push(x); }
int remove() {
if (out.isEmpty()) while (!in.isEmpty()) out.push(in.pop());
return out.pop();
}
}8. What is hashing? Solve “two sum” using a HashMap.
Hashing maps keys to array positions using a hash function, giving O(1) average lookups. For two sum (find two numbers that add up to a target), store each number’s index in a map and check whether target - x has already been seen. O(n) time instead of O(n²).
int[] twoSum(int[] a, int target) {
Map<Integer, Integer> seen = new HashMap<>();
for (int i = 0; i < a.length; i++) {
Integer j = seen.get(target - a[i]);
if (j != null) return new int[]{j, i};
seen.put(a[i], i);
}
return new int[0];
}9. Explain binary search and its condition.
Binary search works only on sorted data. Compare the target with the middle element and discard the half that cannot contain it. O(log n) time.
int binarySearch(int[] a, int key) {
int lo = 0, hi = a.length - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2; // avoids overflow
if (a[mid] == key) return mid;
if (a[mid] < key) lo = mid + 1; else hi = mid - 1;
}
return -1;
}Remember
Key points
- Two pointers
Slow/fast pointers solve many linked-list problems in O(1) space.
- Stack for matching
Brackets, undo and expression problems usually need a stack.
- HashMap for lookups
Turns many O(n²) searches into O(n).
Interview drill
Follow-up questions
What the interviewer asks after your first answer. Turn on practice mode, answer each one aloud, then reveal.
-
1 Find the middle of a linked list in one pass. Basic
Move a slow pointer one step and a fast pointer two steps. When the fast pointer reaches the end, the slow pointer is at the middle.
Node middle(Node head) { Node slow = head, fast = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; } return slow; }Key insight: Fast moves twice as far, so slow ends halfway.
-
2 How would you implement a stack that returns the minimum in O(1)? Intermediate
Keep a second stack that stores the current minimum at each level. Push to it when the new value is less than or equal to its top; pop from it when the popped value equals its top.
void push(int x) { st.push(x); if (mins.isEmpty() || x <= mins.peek()) mins.push(x); } int pop() { int x = st.pop(); if (x == mins.peek()) mins.pop(); return x; } int min() { return mins.peek(); }Key insight: Store extra state alongside each operation.
-
3 What is the difference between a stack overflow and a heap memory error? Intermediate
A
StackOverflowErrorhappens when the call stack runs out, usually from deep or infinite recursion. AnOutOfMemoryErrorhappens when the heap cannot allocate more objects, for example when a collection keeps growing.Key insight: Stack = method calls and locals; heap = objects.
-
4 Merge two sorted linked lists. Intermediate
Use a dummy head and repeatedly attach the smaller of the two current nodes. O(n + m) time, O(1) extra space.
Node merge(Node a, Node b) { Node dummy = new Node(0), t = dummy; while (a != null && b != null) { if (a.val <= b.val) { t.next = a; a = a.next; } else { t.next = b; b = b.next; } t = t.next; } t.next = (a != null) ? a : b; return dummy.next; }Key insight: A dummy node removes special cases for the head.
-
5 When would you choose a circular queue? Advanced
When you need a fixed-size buffer with constant-time enqueue and dequeue and no shifting — for example streaming data, keyboard buffers or producer–consumer pipelines. Indices wrap around using modulo arithmetic.
Key insight: rear = (rear + 1) % capacity reuses freed slots.