DSA Interview Questions 2026: 60 Must-Know Problems With Patterns

DSA interview questions 2026: patterns, Big-O and coding rounds

Last updated: October 2026

Here's something most DSA guides won't tell you: you don't need to solve 800 LeetCode problems. Most people who clear coding rounds at product companies solved somewhere between 150 and 300, but they solved them by pattern. When they see a new problem, they recognise "this is a sliding window" or "this is BFS on a grid" within a minute.

That's how this guide is organised. 60 questions, grouped into the 10 patterns that cover the bulk of what Indian product companies, startups and FAANG-style interviews ask. For each one you get the key idea in plain English and the time complexity you should quote. Code is included where the trick is easier to see than to describe.

DSA interview questions: the quick answer

  • What gets tested: arrays and strings, hashing, two pointers, sliding window, linked lists, stacks, binary search, trees, graphs, heaps, and dynamic programming.
  • Typical format: an online assessment (2–3 problems in 60–90 minutes), then 2–3 live coding rounds of 45–60 minutes, one or two problems each.
  • What interviewers score: a working solution, the right complexity, clean code, testing with edge cases, and how clearly you talk through it.
  • Language: use whatever you're fastest in. Java, C++ and Python are all fine almost everywhere.

How to answer any DSA question in an interview

  1. Repeat the problem in your own words and ask about input size, duplicates, negatives and empty input.
  2. Say the brute force and its complexity. It shows you understand the problem.
  3. Find the pattern and improve. Explain the idea before coding.
  4. Code it cleanly with meaningful names.
  5. Dry run with a small example and one edge case.
  6. State time and space complexity.

Interviewers forgive a small bug. They don't forgive silence.

Big-O quick reference

Data structureAccessSearchInsertDelete
ArrayO(1)O(n)O(n)O(n)
Hash mapn/aO(1) averageO(1) averageO(1) average
Linked listO(n)O(n)O(1) at headO(1) with pointer
Balanced BSTO(log n)O(log n)O(log n)O(log n)
HeapO(1) for min/maxO(n)O(log n)O(log n)

Arrays and hashing (1–8)

1. Two Sum: find two numbers that add up to a target.

Store each number's index in a hash map. For each number, check if target - num is already in the map. O(n) time, O(n) space.

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

2. Check if an array contains duplicates.

Put elements in a set as you go; if one is already there, return true. O(n) time. Sorting first is O(n log n) but uses O(1) extra space, which is a nice trade-off to mention.

3. Group anagrams.

Use the sorted word (or a 26-letter count tuple) as a hash map key. All anagrams land under the same key. O(n · k log k) with sorting, where k is the word length.

4. Find the top K frequent elements.

Count with a hash map, then either keep a min-heap of size K (O(n log k)) or use bucket sort by frequency (O(n)).

5. Product of array except self, without division.

Make one pass for the prefix products from the left and one pass for suffix products from the right. Multiply them. O(n) time, O(1) extra space if you reuse the output array.

6. Longest consecutive sequence in an unsorted array.

Put everything in a set. Only start counting from numbers where num - 1 isn't in the set. Each number is visited at most twice, so O(n).

7. Maximum subarray sum (Kadane's algorithm).

Keep a running sum. If it drops below zero, reset it to zero (or to the current element). Track the best seen. O(n).

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

8. Subarray sum equals K.

Use prefix sums with a hash map counting how often each prefix sum has appeared. At each index, add count[prefix - k] to the answer. O(n). This is the go-to trick when there are negative numbers and sliding window doesn't work.

Two pointers (9–13)

9. Check if a string is a palindrome.

One pointer at each end, moving inward and skipping non-alphanumeric characters if asked. O(n) time, O(1) space.

10. Two Sum on a sorted array.

Left and right pointers. If the sum is too small, move left forward; if it's too big, move right back. O(n), O(1) space.

11. 3Sum: find all unique triplets that sum to zero.

Sort the array. Fix one number, then run two pointers on the rest. Skip duplicates. O(n²).

12. Container with most water.

Pointers at both ends. Area = width × the shorter height. Always move the pointer at the shorter line, because moving the taller one can never help. O(n).

13. Remove duplicates from a sorted array in place.

A slow pointer marks where the next unique value goes; a fast pointer scans. O(n), O(1) space.

Sliding window (14–18)

14. Longest substring without repeating characters.

Expand the right end; when a repeat appears, move the left end past the previous occurrence (store last-seen indexes in a map). O(n).

def longest_unique(s):
    last, left, best = {}, 0, 0
    for right, ch in enumerate(s):
        if ch in last and last[ch] >= left:
            left = last[ch] + 1
        last[ch] = right
        best = max(best, right - left + 1)
    return best

15. Maximum sum of a subarray of size K.

A fixed-size window: add the new element and subtract the one leaving. O(n).

16. Minimum window substring.

A variable window with two count maps. Expand until all needed characters are covered, then shrink from the left while it's still valid, recording the smallest. O(n + m).

17. Longest repeating character replacement.

The window is valid if window length - most frequent char count <= k. Expand right; shrink left when invalid. O(n).

18. Sliding window maximum.

Keep a deque of indexes in decreasing order of value. Drop indexes that fall out of the window from the front, and smaller values from the back. O(n).

Linked lists (19–24)

19. Reverse a linked list.

Walk the list with three pointers: prev, curr, next. Point curr.next to prev and move forward. O(n), O(1).

ListNode reverse(ListNode head) {
    ListNode prev = null, curr = head;
    while (curr != null) {
        ListNode next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
    }
    return prev;
}

20. Detect a cycle in a linked list.

Floyd's algorithm: a slow pointer moves 1 step, a fast pointer moves 2. If they meet, there's a cycle. To find where the cycle starts, reset one pointer to head and move both 1 step until they meet.

21. Find the middle of a linked list.

Slow and fast pointers. When fast reaches the end, slow is in the middle. One pass.

22. Merge two sorted linked lists.

Use a dummy head node and attach the smaller node each time. O(n + m).

23. Remove the Nth node from the end.

Move a fast pointer N steps ahead, then move both pointers together. When fast reaches the end, slow is just before the node to remove. Use a dummy node to handle removing the head.

24. Design an LRU cache.

A hash map from key to node, plus a doubly linked list ordered by recent use. Get and put are both O(1): move the touched node to the front and evict from the back. This is a very common product-company question.

Stacks and queues (25–29)

25. Valid parentheses.

Push opening brackets; on a closing bracket, check that the top of the stack matches. The stack must be empty at the end. O(n).

26. Next greater element.

A monotonic stack: go through the array and, while the current element is bigger than the stack's top, pop it and record the current element as its answer. O(n).

27. Daily temperatures (days until a warmer day).

The same monotonic-stack idea, storing indexes so you can compute the distance. O(n).

28. Implement a queue using two stacks.

Push onto the inbox stack. To pop, if the outbox stack is empty, move everything from inbox to outbox, then pop from outbox. Amortised O(1).

29. Min stack (get the minimum in O(1)).

Keep a second stack (or store pairs) holding the minimum so far at each level.

Binary search (30–34)

30. Classic binary search.

Keep low <= high, compute mid = low + (high - low) / 2 to avoid overflow, and discard half each time. O(log n). Interviewers watch your loop condition and boundary updates closely.

31. Search in a rotated sorted array.

At each step, one half is always sorted. Check whether the target lies in the sorted half; if yes, go there, otherwise go to the other half. O(log n).

32. Find the first and last position of a target.

Run binary search twice: once biased left (keep searching left after a match) and once biased right.

33. Koko eating bananas, or "binary search on the answer".

When the question asks for the minimum speed, capacity or time such that something is possible, binary search over the answer range and check feasibility each time. This pattern covers many "hard-looking" problems.

34. Find the peak element.

Compare mid with mid + 1. If it's increasing, a peak exists on the right; otherwise it's on the left (including mid). O(log n).

Trees (35–43)

35. What are the tree traversals?

Inorder (left, root, right), preorder (root, left, right), postorder (left, right, root) and level order (BFS with a queue). Inorder on a BST gives sorted order.

36. Find the maximum depth of a binary tree.

Recursively: 1 + max(depth(left), depth(right)). O(n).

37. Check if a binary tree is balanced.

Return the height from a post-order helper, and return -1 as soon as any subtree's heights differ by more than 1. One pass, O(n).

38. Validate a binary search tree.

Pass down a valid (min, max) range to each node. Checking only parent–child pairs is the classic wrong answer.

39. Lowest common ancestor of two nodes.

In a BST, walk from the root: if both values are smaller go left, if both are bigger go right, otherwise you've found it. In a general binary tree, recurse; the node where p and q are found in different subtrees is the LCA.

40. Level order traversal.

BFS with a queue. Process len(queue) nodes per level to group the output by level.

41. Diameter of a binary tree.

At each node, a path through it has length left height + right height. Track the maximum while computing heights. O(n).

42. Serialize and deserialize a binary tree.

Preorder traversal with a marker for nulls (such as #), joined by commas. To rebuild, read tokens in the same order recursively.

43. Kth smallest element in a BST.

Inorder traversal and stop at the kth node. O(h + k), where h is the tree height.

Heaps (44–46)

44. Kth largest element in an array.

Keep a min-heap of size K; the top is the answer. O(n log k). Quickselect gives O(n) on average. Mention both.

45. Merge K sorted lists.

Push the head of each list into a min-heap, pop the smallest, and push its next node. O(N log k), where N is the total number of nodes.

46. Find the median from a data stream.

Two heaps: a max-heap for the lower half and a min-heap for the upper half, balanced so their sizes differ by at most one. Adding is O(log n); finding the median is O(1).

Graphs (47–53)

47. BFS vs DFS: when do you use which?

BFS (queue) finds the shortest path in unweighted graphs and works level by level. DFS (recursion or a stack) is natural for exploring all paths, cycle detection, topological sort and connected components.

48. Number of islands.

Scan the grid; on each unvisited land cell, start a DFS or BFS that marks the whole island visited, and count +1. O(rows × cols).

49. Clone a graph.

BFS or DFS with a hash map from each original node to its copy, so cycles don't loop forever.

50. Course schedule (detect a cycle in a directed graph).

Topological sort with Kahn's algorithm: repeatedly take nodes with in-degree 0. If you can't process all nodes, there's a cycle. Or use DFS with three colours (unvisited, visiting, done).

51. Rotting oranges (multi-source BFS).

Put all rotten oranges in the queue at the start and run BFS by levels; each level is one minute. If fresh oranges remain at the end, return -1.

52. Shortest path in a weighted graph.

Dijkstra's algorithm with a min-heap, O((V + E) log V), for non-negative weights. Use Bellman–Ford if there are negative weights.

53. Number of connected components, or redundant connections.

Union-Find (disjoint set) with path compression and union by rank. Nearly O(1) per operation. Good to know for any "are these connected" question.

Dynamic programming (54–60)

54. How do you recognise a DP problem?

It asks for a count, a minimum/maximum, or "is it possible", and choices at each step lead to overlapping subproblems. Start with recursion, add memoization, then convert to a bottom-up table if needed.

55. Climbing stairs (1 or 2 steps at a time).

ways(n) = ways(n-1) + ways(n-2), Fibonacci in disguise. O(n) time, O(1) space with two variables.

56. House robber.

dp[i] = max(dp[i-1], dp[i-2] + nums[i]): either skip this house or rob it plus the best from two houses back.

57. Coin change (fewest coins).

dp[amount] = min(dp[amount - coin] + 1) over all coins, with dp[0] = 0. O(amount × coins).

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

58. Longest increasing subsequence.

The O(n²) DP: dp[i] = 1 + max(dp[j]) for j < i where nums[j] < nums[i]. The O(n log n) version keeps a "tails" array and uses binary search. Knowing both impresses interviewers.

59. Longest common subsequence.

A 2D table: if the characters match, dp[i][j] = dp[i-1][j-1] + 1, otherwise max(dp[i-1][j], dp[i][j-1]). O(n × m). Edit distance uses the same shape.

60. 0/1 knapsack.

dp[w] = max(dp[w], dp[w - weight] + value), looping weights from high to low so each item is used at most once. O(n × W). Many "subset sum" and "partition equal subset" problems are this in disguise.

Common mistakes candidates make

  • Coding before explaining. Spend the first 5 minutes on approach.
  • Ignoring edge cases: empty input, one element, all duplicates, negative numbers, integer overflow.
  • Memorising solutions instead of patterns. Interviewers change one detail and the memorised answer falls apart.
  • Not stating complexity, or stating it wrong for recursive solutions.
  • Never practising out loud. Do at least five mock interviews with a friend or a platform.

A 4-week DSA prep plan

WeekPatternsTarget
1Arrays, hashing, two pointers, sliding window40 easy and medium problems
2Linked lists, stacks, binary search35 problems
3Trees, heaps, graphs (BFS, DFS, topological sort, union-find)40 problems
4Dynamic programming plus mixed timed sets30 problems + 4 mock interviews

The NeetCode 150 list or Striver's SDE sheet covers this well. Pick one list and finish it rather than hopping between five.

Where DSA matters most

DSA decides the coding rounds at product companies, unicorns, fintechs and global tech companies, and the online tests at mass recruiters too. See how it fits into specific processes in our Amazon interview questions, Google interview questions and TCS interview questions guides.

For language-specific rounds, see Java interview questions and Python interview questions. Curious what strong DSA can lead to? Check the software engineer salary guide and Weekday's company salary pages.

Frequently asked questions

How many DSA problems should I solve before interviews?

Quality beats quantity. 150–300 problems covering every major pattern, with a few revisited until you can solve them without hints, is enough for most product company interviews.

Which language is best for DSA interviews?

The one you're fastest and most accurate in. C++ and Java are popular in India; Python is shorter to write. Interviewers rarely care, as long as you know your language's standard library.

Is DSA asked for freshers at service companies?

Yes, at a lighter level. TCS, Infosys, Wipro and others include coding questions in their online tests, usually arrays, strings and basic logic rather than graphs or DP.

Do experienced developers still get DSA rounds?

At most product companies, yes, usually alongside system design. The bar is often medium-level problems, solved cleanly and quickly.

How long does it take to prepare DSA from scratch?

With 2–3 hours a day, about 3–4 months to become comfortable with medium problems. With a strong base, 4–6 weeks of focused revision is typical.


Ready to put the practice to work? Find software engineering jobs on Weekday and run your resume through our free ATS resume checker first.

Latest Articles

Browse Articles
Use AI to find jobs and apply

Stop manually filling job applications. Use AI to auto-apply to jobs

Browse jobs now