50 DSA Interview Questions for 2026 Fresher Coding Rounds
The 50 DSA questions most likely to appear in 2026 IT-services and product-company coding rounds, with solutions and complexity. Start with arrays, strings, stacks and linked lists — services loops lean on them.
Say you have an Infosys or TCS interview next week and fifty DSA questions on your list. The first question is often "reverse an array" or "find two numbers that add up to a target". A weak answer is a long silence followed by a nested loop. A strong one names the simple loop, says what it costs, then improves it out loud.
Drill arrays, strings, basic stacks and queues, and easy linked lists first, because off-campus IT-services loops lean on them. Add trees and graphs, and dynamic programming as well, only if you are aiming at product companies. Below are fifty questions grouped by topic, each with a short solution, its time and space complexity, and what the interviewer is checking.
Which DSA topics each type of company asks
IT-services loops stay mostly on arrays and strings, with some stacks and queues and easy linked lists, while product-company loops add trees and graphs, plus dynamic programming and medium or hard problems.
Skipping DSA is not an option for a services role either. Internshala reports that more than 70% of technical interviews feature data structures and algorithms questions. The Infosys drive is services work, so the middle column of this table is where most of those seats get decided.
The topic list comes from the GeeksforGeeks Top 100 DSA questions, which groups questions by data structure. The split between the two columns is my reading of how the two kinds of loop differ, not an official syllabus.
| Topic | IT-services loops | Product-company loops | Difficulty to expect |
|---|---|---|---|
| Arrays | Almost always | Almost always | Easy to medium |
| Strings | Almost always | Often | Easy to medium |
| Stacks and queues | Often | Often | Easy |
| Linked lists | Sometimes, easy ones | Often | Easy to medium |
| Searching and sorting | Often, as follow-ups | Often | Easy |
| Trees | Rare | Common | Medium |
| Graphs | Rare | Common | Medium to hard |
| Dynamic programming | Rare | Common | Medium to hard |
| Heaps and bit manipulation | Rare | Sometimes | Medium |
Targeting TCS? Read our note on TCS's Q2 FY27 fresher hiring before deciding how far down the table to go.
Optional extra: this Apna College video walks through must-do placement problems, so watch it after you have tried the first ten questions below.
Array questions (1-10)
Arrays are the most common first question, and the interviewer checks whether you can reach a loop-based answer and say why it is O(n).
# 1. Reverse an array: O(n) time, O(1) space
def rev(a, i, j):
while i < j:
a[i], a[j] = a[j], a[i]
i, j = i + 1, j - 1
return a
# call: rev(a, 0, len(a) - 1)
# 2. Largest and second largest: O(n) time, O(1) space (second must be strictly smaller than first, so [5, 5] returns -inf for second)
def top_two(a):
first = second = float('-inf')
for x in a:
if x > first:
first, second = x, first
elif first > x > second:
second = x
return first, second
# 3. Two-sum: O(n) time, O(n) space
def two_sum(a, target):
seen = {}
for i, x in enumerate(a):
if target - x in seen:
return seen[target - x], i
seen[x] = i
# 4. Move zeros to the end: O(n) time, O(1) space
def move_zeros(a):
k = 0
for x in a:
if x != 0:
a[k] = x; k += 1
for i in range(k, len(a)):
a[i] = 0
return a
# 5. Kadane's maximum subarray: O(n) time, O(1) space
def max_subarray(a):
best = cur = a[0]
for x in a[1:]:
cur = max(x, cur + x)
best = max(best, cur)
return best
# 6. Rotate right by k: O(n) time, O(1) space (k = 0 works because rev(a, 0, -1) does nothing)
def rotate(a, k):
n = len(a); k %= n
rev(a, 0, n - 1); rev(a, 0, k - 1); rev(a, k, n - 1)
# 7. Missing number in 0..n: O(n) time, O(1) space
def missing(a):
n = len(a)
return n * (n + 1) // 2 - sum(a)
# 8. Remove duplicates from a sorted array: O(n) time, O(1) space
def dedupe_sorted(a):
if not a: return 0
k = 1
for i in range(1, len(a)):
if a[i] != a[k - 1]:
a[k] = a[i]; k += 1
return k
# 9. Merge two sorted arrays: O(n + m) time, O(n + m) space
def merge(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:]
# 10. Majority element (Boyer-Moore vote): O(n) time, O(1) space
def majority(a):
cand, count = None, 0
for x in a:
if count == 0: cand = x
count += 1 if x == cand else -1
return cand
Drill these ten before anything else. Question 10 assumes a majority exists, so say that assumption out loud before you code it.
Here is a weak and a strong spoken answer to question 3. Weak: silence, then 'I will loop inside a loop.' Strong: 'The simple way checks every pair, which is O(n²) time and O(1) space. I can do better by storing each number I have seen in a dictionary, then asking whether target minus the current number is already there. That is O(n) time and O(n) space, and I am trading memory for speed.'
Question 10 in plain words: keep one candidate and a count. A value equal to the candidate adds one, a different value cancels one, and when the count hits zero you pick a new candidate. A true majority outnumbers everything else, so it survives the cancelling. On [2, 2, 1, 1, 2] the count goes 1, 2, 1, 0, 1 and the answer is 2.
String questions (11-20)
String questions test whether you handle edge cases such as empty input and letter case, then spaces, before you reach for a clever trick.
from collections import Counter
# 11. Reverse a string: O(n) time, O(n) space
def reverse_str(s): return s[::-1]
# 12. Palindrome, ignoring case and spaces: O(n) time, O(n) space
def is_palindrome(s):
clean = [c.lower() for c in s if c.isalnum()]
return clean == clean[::-1]
# 13. Valid anagram: O(n) time, O(k) space for k distinct characters
def is_anagram(s, t): return Counter(s) == Counter(t)
# 14. First non-repeating character: O(n) time, O(k) space
def first_unique(s):
counts = Counter(s)
for c in s:
if counts[c] == 1: return c
return None
# 15. Count vowels: O(n) time, O(1) space
def vowels(s): return sum(c in 'aeiouAEIOU' for c in s)
# 16. Longest common prefix: O(n * m) time, O(m) space, n = number of words, m = length of the first word
def lcp(words):
if not words: return ""
p = words[0]
for w in words[1:]:
while not w.startswith(p): p = p[:-1]
return p
# 17. Is b a rotation of a? O(n) time with a good substring search (n = len(a)), O(n) space
def is_rotation(a, b): return len(a) == len(b) and b in a + a
# 18. Remove duplicate characters, keep order: O(n) time, O(n) space
def remove_dupes(s): return "".join(dict.fromkeys(s))
# 19. String compression, "aabccc" to "a2b1c3": O(n) time, O(n) space
def compress(s):
out, i = [], 0
while i < len(s):
j = i
while j < len(s) and s[j] == s[i]: j += 1
out.append(s[i] + str(j - i)); i = j
r = "".join(out)
return r if len(r) < len(s) else s
# 20. Longest substring without repeating characters: O(n) time, O(k) space
def longest_unique(s):
last, start, best = {}, 0, 0
for i, c in enumerate(s):
if last.get(c, -1) >= start: start = last[c] + 1
last[c] = i
best = max(best, i - start + 1)
return best
Question 20 in plain words: keep a window that never contains a repeated character. When the current character was last seen inside the window, move the window start just past that earlier spot. On "abcabcbb" the window grows to "abc" (best 3), then start moves to 1, 2, 3 as a, b and c repeat. It later shrinks to "cb" and "b", so the function returns 3.
Question 13 has two honest answers. Here is how sorting both strings compares with the hash-map count above:
Pros
- Sorting is one line:
sorted(s) == sorted(t). - It is easy to explain under pressure.
Cons
- Sorting costs O(n log n), against O(n) for counting.
- The interviewer will almost always ask for the faster version next.
Linked list questions (21-28)
Linked list questions check whether you can track pointers without losing the rest of the list.
class Node:
def __init__(self, val, nxt=None):
self.val, self.next = val, nxt
# 21. Reverse a list: O(n) time, O(1) space
def reverse_list(head):
prev = None
while head:
head.next, prev, head = prev, head, head.next
return prev
# 22. Middle node (slow and fast pointers): O(n) time, O(1) space
def middle(head):
slow = fast = head
while fast and fast.next:
slow, fast = slow.next, fast.next.next
return slow
# 23. Detect a cycle: O(n) time, O(1) space
def has_cycle(head):
slow = fast = head
while fast and fast.next:
slow, fast = slow.next, fast.next.next
if slow is fast: return True
return False
# 24. Merge two sorted lists: O(n + m) time, O(1) space
def merge_lists(a, b):
dummy = tail = Node(0)
while a and b:
if a.val <= b.val: tail.next, a = a, a.next
else: tail.next, b = b, b.next
tail = tail.next
tail.next = a or b
return dummy.next
# 25. Remove the nth node from the end: O(n) time, O(1) space
def remove_nth(head, n):
dummy = Node(0, head); fast = slow = dummy
for _ in range(n): fast = fast.next
while fast.next:
fast, slow = fast.next, slow.next
slow.next = slow.next.next
return dummy.next
# 26. Palindrome list (changes the second half): O(n) time, O(1) space
def is_pal(head):
second = reverse_list(middle(head))
while second:
if head.val != second.val: return False
head, second = head.next, second.next
return True
# 27. Delete a node given only that node (not the tail): O(1) time and space
def delete_node(node):
node.val, node.next = node.next.val, node.next.next
# 28. Intersection of two lists: O(n + m) time, O(1) space
def intersection(a, b):
p, q = a, b
while p is not q:
p = p.next if p else b
q = q.next if q else a
return p
Question 21 in plain words: the right side of head.next, prev, head = prev, head, head.next is worked out first, using the old values. Then the assignments run left to right, so the current node points backwards, prev moves up to the current node, and head moves on to the node that came next.
Question 25 in plain words: move fast n steps ahead, then move both pointers until fast sits on the last node. Slow is now just before the node to delete, so slow.next = slow.next.next skips it.
Question 28 in plain words: each pointer walks its own list and then switches to the start of the other list. Both walk the same total distance, so they meet at the shared node, or both reach the end together if there is none. Take a = 1, 2, 8, 9 and b = 5, 8, 9, where 8 and 9 are shared. The pairs (p, q) go (1, 5), (2, 8), (8, 9), (9, None), (None, 1), (5, 2), (8, 8). They meet, so the function returns the node 8.
Stack and queue questions (29-36)
Stack and queue questions check whether you know when last-in-first-out or first-in-first-out fits the problem.
import operator
from collections import deque
# 29. Valid parentheses: O(n) time, O(n) space
def valid(s):
pairs = {')': '(', ']': '[', '}': '{'}
stack = []
for c in s:
if c in pairs:
if not stack or stack.pop() != pairs[c]: return False
else: stack.append(c)
return not stack
# 30. Stack using an array: O(1) per operation (amortised push)
class Stack:
def __init__(self): self.items = []
def push(self, x): self.items.append(x)
def pop(self): return self.items.pop()
def peek(self): return self.items[-1]
# 31. Queue using two stacks: amortised O(1) per operation, O(n) space
class Queue:
def __init__(self): self.inbox, self.outbox = [], []
def push(self, x): self.inbox.append(x)
def pop(self):
if not self.outbox:
while self.inbox: self.outbox.append(self.inbox.pop())
return self.outbox.pop()
# 32. Min stack: O(1) per operation, O(n) space
class MinStack:
def __init__(self): self.s = []
def push(self, x):
m = min(x, self.s[-1][1]) if self.s else x
self.s.append((x, m))
def pop(self): return self.s.pop()[0]
def get_min(self): return self.s[-1][1]
# 33. Next greater element: O(n) time, O(n) space
def next_greater(a):
res, stack = [-1] * len(a), []
for i, x in enumerate(a):
while stack and a[stack[-1]] < x:
res[stack.pop()] = x
stack.append(i)
return res
# 34. Evaluate a postfix expression: O(n) time, O(n) space
OPS = {'+': operator.add, '-': operator.sub,
'*': operator.mul, '/': lambda a, b: int(a / b)}
def eval_postfix(tokens):
st = []
for t in tokens:
if t in OPS:
b, a = st.pop(), st.pop()
st.append(OPS[t](a, b))
else: st.append(int(t))
return st[0]
# 35. Circular queue of size k: O(1) per operation, O(k) space
class CircularQueue:
def __init__(self, k):
self.q, self.head, self.size = [None] * k, 0, 0
def enqueue(self, x):
if self.size == len(self.q): return False
self.q[(self.head + self.size) % len(self.q)] = x
self.size += 1; return True
def dequeue(self):
if self.size == 0: return None
x = self.q[self.head]
self.head = (self.head + 1) % len(self.q); self.size -= 1
return x
# 36. Reverse a queue with a stack: O(n) time, O(n) space
def reverse_queue(q):
stack = []
while q: stack.append(q.popleft())
while stack: q.append(stack.pop())
return q
Here is how the stack in question 29 changes on the input ({[]}):
- Read
(: push it. Stack:( - Read
{: push it. Stack:( { - Read
[: push it. Stack:( { [ - Read
]: pop[, which matches. Stack:( { - Read
}: pop{, which matches. Stack:( - Read
): pop(, which matches. The stack is empty, so the string is valid.
Question 33 in plain words: the stack holds indexes of numbers still waiting for a bigger one. Each new number settles every waiting number smaller than it. On [2, 1, 3], the 1 and then the 2 are both settled by the 3, so the result is [3, 3, -1].
Searching, sorting and recursion basics (37-42)
Binary search and the basic sorts are favourite follow-ups because they show whether you understand time complexity, not just syntax.
from functools import lru_cache
# 37. Binary search on a sorted array: O(log n) time, O(1) space
def binary_search(a, x):
lo, hi = 0, len(a) - 1
while lo <= hi:
mid = (lo + hi) // 2
if a[mid] == x: return mid
if a[mid] < x: lo = mid + 1
else: hi = mid - 1
return -1
# 38. First and last position: O(log n) time, O(1) space
def bound(a, x, first):
lo, hi, ans = 0, len(a) - 1, -1
while lo <= hi:
mid = (lo + hi) // 2
if a[mid] == x:
ans = mid
if first: hi = mid - 1
else: lo = mid + 1
elif a[mid] < x: lo = mid + 1
else: hi = mid - 1
return ans
# answer: [bound(a, x, True), bound(a, x, False)]
# 39. Merge sort (uses merge from question 9): O(n log n) time, O(n) space
def merge_sort(a):
if len(a) <= 1: return a
m = len(a) // 2
return merge(merge_sort(a[:m]), merge_sort(a[m:]))
# 40. Quick sort (simple, not in place): O(n log n) average time
def quick_sort(a):
if len(a) <= 1: return a
p = a[len(a) // 2]
return (quick_sort([x for x in a if x < p]) + [x for x in a if x == p]
+ quick_sort([x for x in a if x > p]))
# 41. Factorial: O(n) time, O(n) stack. Fibonacci with memo: O(n) time
# plain version, O(2^n): def fib_plain(n): return n if n < 2 else fib_plain(n - 1) + fib_plain(n - 2)
def fact(n): return 1 if n <= 1 else n * fact(n - 1)
@lru_cache(None)
def fib(n): return n if n < 2 else fib(n - 1) + fib(n - 2)
# 42. Power x^n for n >= 0: O(log n) time, O(log n) stack
def power(x, n):
if n == 0: return 1
half = power(x, n // 2)
return half * half * (x if n % 2 else 1)
| Sort | Best | Average | Worst | Extra space |
|---|---|---|---|---|
| Bubble sort (with an early-exit flag) | O(n) | O(n²) | O(n²) | O(1) |
| Merge sort | O(n log n) | O(n log n) | O(n log n) | O(n) |
| Quick sort (in place) | O(n log n) | O(n log n) | O(n²) | O(log n) |
Trees, graphs and dynamic programming (43-50)
These topics mostly appear in product-company loops, so a fresher aiming at services firms can leave them for later.
from collections import deque
# 43. Inorder traversal: O(n) time, O(h) stack for tree height h
def inorder(node):
return inorder(node.left) + [node.val] + inorder(node.right) if node else []
# 44. Maximum depth: O(n) time, O(h) space
def depth(node):
return 1 + max(depth(node.left), depth(node.right)) if node else 0
# 45. Validate a BST: O(n) time, O(h) space
def is_bst(node, lo=float('-inf'), hi=float('inf')):
if not node: return True
if not lo < node.val < hi: return False
return is_bst(node.left, lo, node.val) and is_bst(node.right, node.val, hi)
# 46. Level-order traversal: O(n) time, O(n) space
def level_order(root):
if not root: return []
out, q = [], deque([root])
while q:
level = []
for _ in range(len(q)):
n = q.popleft(); level.append(n.val)
if n.left: q.append(n.left)
if n.right: q.append(n.right)
out.append(level)
return out
# 47. BFS on a graph (adjacency dict): O(V + E) time, O(V) space
def bfs(graph, start):
seen, q, order = {start}, deque([start]), []
while q:
u = q.popleft(); order.append(u)
for v in graph[u]:
if v not in seen: seen.add(v); q.append(v)
return order
# 48. Count islands with DFS: O(rows * cols) time and space
def count_islands(grid):
rows, cols, count = len(grid), len(grid[0]), 0
def sink(r, c):
if 0 <= r < rows and 0 <= c < cols and grid[r][c] == '1':
grid[r][c] = '0'
sink(r + 1, c); sink(r - 1, c); sink(r, c + 1); sink(r, c - 1)
for r in range(rows):
for c in range(cols):
if grid[r][c] == '1': count += 1; sink(r, c)
return count
# 49. Climbing stairs (1 or 2 steps): O(n) time, O(1) space
def climb(n):
a, b = 1, 1
for _ in range(n): a, b = b, a + b
return a
# 50. Coin change, fewest coins: O(amount * coins) time, O(amount) space
def coin_change(coins, amount):
dp = [0] + [float('inf')] * amount
for x in range(1, amount + 1):
for c in coins:
if c <= x: dp[x] = min(dp[x], dp[x - c] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
Drill order for the next two weeks
Spend week one on questions 1-36 and week two on questions 37-42, then on 43-50 only if you are aiming at product companies, because clear explanation at the fresher level counts for more than complex code.
Run every question through the same four steps:
Solve
Write the simple version first, even if it is slow.
Explain aloud
Talk through it as if the interviewer were across the table. Say why each line exists.
State complexity
Give time and space, then name the line that sets each one.
Redo without notes
Close the file. Come back the next day and write it again from a blank page.
This page is the question bank. For the patterns behind these questions and how company rounds are structured, read Crack Your First Coding Interview in India. To show this practice on paper, see which skills to list on a fresher resume.
Someone still has to read generated code and say whether it runs in O(n) or O(n²), so practise saying it.
Pick five array questions from the bank today. Solve each without looking at the answer, then say your solution out loud and state its time and space complexity. Tomorrow, do the same with five string questions.