Coding interviews at top tech companies test data structures, algorithms, and problem-solving skills. This guide covers the 50 most frequently asked problems — with optimal solutions, time/space complexity, and patterns to recognise.
Quick reference
| Pattern | Problems covered |
|---|---|
| Arrays & Hashing | Two Sum, Contains Duplicate, Anagram |
| Two Pointers | Valid Palindrome, 3Sum, Container With Most Water |
| Sliding Window | Longest Substring, Minimum Window Substring |
| Stack | Valid Parentheses, Daily Temperatures, Min Stack |
| Binary Search | Search Rotated, Find Minimum, Koko Eating Bananas |
| Linked Lists | Reverse List, Merge Lists, Detect Cycle |
| Trees | Max Depth, Same Tree, LCA, Level Order |
| Graphs | Number of Islands, Clone Graph, Course Schedule |
| Dynamic Programming | Climbing Stairs, Coin Change, Longest Common Subsequence |
| Greedy | Jump Game, Merge Intervals, Meeting Rooms |
Arrays and hashing
1. Two Sum
Problem: Given an array of integers nums and a target, return indices of two numbers that add up to the target.
Pattern: Hash map — store complement as you iterate.
def twoSum(nums, target):
seen = {}
for i, n in enumerate(nums):
complement = target - n
if complement in seen:
return [seen[complement], i]
seen[n] = i
function twoSum(nums, target) {
const seen = new Map();
for (let i = 0; i < nums.length; i++) {
const complement = target - nums[i];
if (seen.has(complement)) return [seen.get(complement), i];
seen.set(nums[i], i);
}
}
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(n) |
Key insight: One pass — check map before inserting.
2. Contains Duplicate
Problem: Return true if any value appears more than once.
def containsDuplicate(nums):
return len(nums) != len(set(nums))
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(n) |
Follow-up: For large arrays, sort first (O(n log n), O(1) space) then check adjacent elements.
3. Valid Anagram
Problem: Given strings s and t, return true if t is an anagram of s.
from collections import Counter
def isAnagram(s, t):
return Counter(s) == Counter(t)
# Space-optimised (26 letters only)
def isAnagram(s, t):
if len(s) != len(t):
return False
count = [0] * 26
for a, b in zip(s, t):
count[ord(a) - ord('a')] += 1
count[ord(b) - ord('a')] -= 1
return all(c == 0 for c in count)
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(1) — only 26 letters |
4. Group Anagrams
Problem: Group strings that are anagrams of each other.
from collections import defaultdict
def groupAnagrams(strs):
groups = defaultdict(list)
for s in strs:
key = tuple(sorted(s))
groups[key].append(s)
return list(groups.values())
| Complexity | |
|---|---|
| Time | O(n · k log k) where k = max string length |
| Space | O(n · k) |
Optimisation: Use character count tuple as key instead of sorted string — O(n · k) time.
5. Top K Frequent Elements
Problem: Return the k most frequent elements.
import heapq
from collections import Counter
def topKFrequent(nums, k):
count = Counter(nums)
return heapq.nlargest(k, count.keys(), key=count.get)
# Bucket sort — O(n)
def topKFrequent(nums, k):
count = Counter(nums)
buckets = [[] for _ in range(len(nums) + 1)]
for num, freq in count.items():
buckets[freq].append(num)
result = []
for i in range(len(buckets) - 1, 0, -1):
result.extend(buckets[i])
if len(result) >= k:
return result[:k]
| Approach | Time | Space |
|---|---|---|
| Heap | O(n log k) | O(n) |
| Bucket sort | O(n) | O(n) |
Two pointers
6. Valid Palindrome
Problem: A string is a palindrome if — after removing non-alphanumeric characters and lowercasing — it reads the same forwards and backwards.
def isPalindrome(s):
left, right = 0, len(s) - 1
while left < right:
while left < right and not s[left].isalnum():
left += 1
while left < right and not s[right].isalnum():
right -= 1
if s[left].lower() != s[right].lower():
return False
left += 1
right -= 1
return True
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(1) |
7. 3Sum
Problem: Find all unique triplets that sum to zero.
def threeSum(nums):
nums.sort()
result = []
for i, n in enumerate(nums):
if i > 0 and nums[i] == nums[i - 1]:
continue # skip duplicates
left, right = i + 1, len(nums) - 1
while left < right:
total = n + nums[left] + nums[right]
if total == 0:
result.append([n, nums[left], nums[right]])
left += 1
while left < right and nums[left] == nums[left - 1]:
left += 1
elif total < 0:
left += 1
else:
right -= 1
return result
| Complexity | |
|---|---|
| Time | O(n²) |
| Space | O(1) excluding output |
Pattern: Sort → fix one element → two-pointer scan.
8. Container With Most Water
Problem: Given heights of vertical lines, find two that form a container holding the most water.
def maxArea(height):
left, right = 0, len(height) - 1
max_water = 0
while left < right:
water = min(height[left], height[right]) * (right - left)
max_water = max(max_water, water)
if height[left] < height[right]:
left += 1
else:
right -= 1
return max_water
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(1) |
Key insight: Move the shorter side inward — moving the taller side can only decrease area.
Sliding window
9. Longest Substring Without Repeating Characters
def lengthOfLongestSubstring(s):
char_index = {}
left = max_len = 0
for right, char in enumerate(s):
if char in char_index and char_index[char] >= left:
left = char_index[char] + 1
char_index[char] = right
max_len = max(max_len, right - left + 1)
return max_len
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(min(n, charset)) |
10. Minimum Window Substring
Problem: Find the minimum window in s that contains all characters of t.
from collections import Counter
def minWindow(s, t):
if not t:
return ""
need = Counter(t)
have, required = 0, len(need)
window = {}
result = ""
result_len = float("inf")
left = 0
for right, char in enumerate(s):
window[char] = window.get(char, 0) + 1
if char in need and window[char] == need[char]:
have += 1
while have == required:
if (right - left + 1) < result_len:
result_len = right - left + 1
result = s[left:right + 1]
window[s[left]] -= 1
if s[left] in need and window[s[left]] < need[s[left]]:
have -= 1
left += 1
return result
| Complexity | |
|---|---|
| Time | O(∣s∣ + ∣t∣) |
| Space | O(∣s∣ + ∣t∣) |
Stack
11. Valid Parentheses
def isValid(s):
stack = []
pairs = {')': '(', ']': '[', '}': '{'}
for char in s:
if char in pairs:
if not stack or stack[-1] != pairs[char]:
return False
stack.pop()
else:
stack.append(char)
return not stack
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(n) |
12. Daily Temperatures
Problem: Return array where each element is the number of days until a warmer temperature.
def dailyTemperatures(temperatures):
result = [0] * len(temperatures)
stack = [] # (temp, index)
for i, t in enumerate(temperatures):
while stack and t > stack[-1][0]:
_, idx = stack.pop()
result[idx] = i - idx
stack.append((t, i))
return result
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(n) |
Pattern: Monotonic decreasing stack.
13. Min Stack
Problem: Stack supporting push, pop, top, and getMin in O(1).
class MinStack:
def __init__(self):
self.stack = []
self.min_stack = []
def push(self, val):
self.stack.append(val)
min_val = min(val, self.min_stack[-1] if self.min_stack else val)
self.min_stack.append(min_val)
def pop(self):
self.stack.pop()
self.min_stack.pop()
def top(self):
return self.stack[-1]
def getMin(self):
return self.min_stack[-1]
Binary search
14. Binary Search
def search(nums, target):
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
| Complexity | |
|---|---|
| Time | O(log n) |
| Space | O(1) |
15. Search in Rotated Sorted Array
def search(nums, target):
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
# Left half is sorted
if nums[left] <= nums[mid]:
if nums[left] <= target < nums[mid]:
right = mid - 1
else:
left = mid + 1
# Right half is sorted
else:
if nums[mid] < target <= nums[right]:
left = mid + 1
else:
right = mid - 1
return -1
Key insight: One half is always sorted — determine which half and binary search within it.
16. Find Minimum in Rotated Sorted Array
def findMin(nums):
left, right = 0, len(nums) - 1
while left < right:
mid = (left + right) // 2
if nums[mid] > nums[right]:
left = mid + 1
else:
right = mid
return nums[left]
| Complexity | |
|---|---|
| Time | O(log n) |
| Space | O(1) |
Linked lists
17. Reverse a Linked List
def reverseList(head):
prev = None
curr = head
while curr:
next_node = curr.next
curr.next = prev
prev = curr
curr = next_node
return prev
# Recursive
def reverseList(head):
if not head or not head.next:
return head
new_head = reverseList(head.next)
head.next.next = head
head.next = None
return new_head
| Approach | Time | Space |
|---|---|---|
| Iterative | O(n) | O(1) |
| Recursive | O(n) | O(n) stack |
18. Merge Two Sorted Lists
def mergeTwoLists(list1, list2):
dummy = ListNode(0)
curr = dummy
while list1 and list2:
if list1.val <= list2.val:
curr.next = list1
list1 = list1.next
else:
curr.next = list2
list2 = list2.next
curr = curr.next
curr.next = list1 or list2
return dummy.next
| Complexity | |
|---|---|
| Time | O(n + m) |
| Space | O(1) |
19. Linked List Cycle Detection
def hasCycle(head):
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
Pattern: Floyd's Tortoise and Hare — fast pointer moves 2x, they meet if cycle exists.
20. Find Cycle Start
def detectCycle(head):
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
# Reset slow to head
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return slow
return None
21. Reorder List
Problem: Reorder L0→L1→...→Ln as L0→Ln→L1→Ln-1→...
def reorderList(head):
# Find middle
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# Reverse second half
prev, curr = None, slow.next
slow.next = None
while curr:
next_node = curr.next
curr.next = prev
prev = curr
curr = next_node
# Merge
first, second = head, prev
while second:
tmp1, tmp2 = first.next, second.next
first.next = second
second.next = tmp1
first, second = tmp1, tmp2
Trees
22. Maximum Depth of Binary Tree
def maxDepth(root):
if not root:
return 0
return 1 + max(maxDepth(root.left), maxDepth(root.right))
# Iterative BFS
from collections import deque
def maxDepth(root):
if not root:
return 0
depth = 0
queue = deque([root])
while queue:
depth += 1
for _ in range(len(queue)):
node = queue.popleft()
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
return depth
23. Same Tree
def isSameTree(p, q):
if not p and not q:
return True
if not p or not q or p.val != q.val:
return False
return isSameTree(p.left, q.left) and isSameTree(p.right, q.right)
24. Invert Binary Tree
def invertTree(root):
if not root:
return None
root.left, root.right = invertTree(root.right), invertTree(root.left)
return root
25. Lowest Common Ancestor of BST
def lowestCommonAncestor(root, p, q):
while root:
if p.val < root.val and q.val < root.val:
root = root.left
elif p.val > root.val and q.val > root.val:
root = root.right
else:
return root
Key insight: In a BST, if both values are smaller go left; if both larger go right; else current node is LCA.
26. Level Order Traversal
from collections import deque
def levelOrder(root):
if not root:
return []
result = []
queue = deque([root])
while queue:
level = []
for _ in range(len(queue)):
node = queue.popleft()
level.append(node.val)
if node.left: queue.append(node.left)
if node.right: queue.append(node.right)
result.append(level)
return result
27. Validate Binary Search Tree
def isValidBST(root, min_val=float('-inf'), max_val=float('inf')):
if not root:
return True
if not (min_val < root.val < max_val):
return False
return (isValidBST(root.left, min_val, root.val) and
isValidBST(root.right, root.val, max_val))
28. Kth Smallest in BST
def kthSmallest(root, k):
stack = []
curr = root
count = 0
while curr or stack:
while curr:
stack.append(curr)
curr = curr.left
curr = stack.pop()
count += 1
if count == k:
return curr.val
curr = curr.right
Pattern: In-order traversal of BST gives sorted order.
29. Serialize and Deserialize Binary Tree
class Codec:
def serialize(self, root):
result = []
def dfs(node):
if not node:
result.append('N')
return
result.append(str(node.val))
dfs(node.left)
dfs(node.right)
dfs(root)
return ','.join(result)
def deserialize(self, data):
vals = iter(data.split(','))
def dfs():
val = next(vals)
if val == 'N':
return None
node = TreeNode(int(val))
node.left = dfs()
node.right = dfs()
return node
return dfs()
Graphs
30. Number of Islands
Problem: Count the number of islands in a 2D grid.
def numIslands(grid):
if not grid:
return 0
rows, cols = len(grid), len(grid[0])
count = 0
def dfs(r, c):
if r < 0 or c < 0 or r >= rows or c >= cols or grid[r][c] != '1':
return
grid[r][c] = '0' # mark visited
dfs(r + 1, c); dfs(r - 1, c)
dfs(r, c + 1); dfs(r, c - 1)
for r in range(rows):
for c in range(cols):
if grid[r][c] == '1':
count += 1
dfs(r, c)
return count
| Complexity | |
|---|---|
| Time | O(m · n) |
| Space | O(m · n) stack |
31. Clone Graph
def cloneGraph(node):
if not node:
return None
cloned = {}
def dfs(n):
if n in cloned:
return cloned[n]
clone = Node(n.val)
cloned[n] = clone
for neighbor in n.neighbors:
clone.neighbors.append(dfs(neighbor))
return clone
return dfs(node)
32. Course Schedule (Detect Cycle in Directed Graph)
def canFinish(numCourses, prerequisites):
graph = [[] for _ in range(numCourses)]
for course, pre in prerequisites:
graph[pre].append(course)
# 0 = unvisited, 1 = visiting, 2 = done
state = [0] * numCourses
def dfs(node):
if state[node] == 1:
return False # cycle
if state[node] == 2:
return True
state[node] = 1
for neighbor in graph[node]:
if not dfs(neighbor):
return False
state[node] = 2
return True
return all(dfs(i) for i in range(numCourses))
33. Word Ladder
Problem: Find shortest transformation sequence from beginWord to endWord.
from collections import deque, defaultdict
def ladderLength(beginWord, endWord, wordList):
word_set = set(wordList)
if endWord not in word_set:
return 0
# Build pattern map
patterns = defaultdict(list)
for word in wordList:
for i in range(len(word)):
pattern = word[:i] + '*' + word[i+1:]
patterns[pattern].append(word)
queue = deque([(beginWord, 1)])
visited = {beginWord}
while queue:
word, steps = queue.popleft()
if word == endWord:
return steps
for i in range(len(word)):
pattern = word[:i] + '*' + word[i+1:]
for neighbor in patterns[pattern]:
if neighbor not in visited:
visited.add(neighbor)
queue.append((neighbor, steps + 1))
return 0
Dynamic programming
34. Climbing Stairs
Problem: n stairs, can take 1 or 2 steps. How many distinct ways to reach the top?
def climbStairs(n):
if n <= 2:
return n
prev, curr = 1, 2
for _ in range(3, n + 1):
prev, curr = curr, prev + curr
return curr
Pattern: Fibonacci — dp[n] = dp[n-1] + dp[n-2].
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(1) |
35. Coin Change
Problem: Minimum coins needed to make amount.
def coinChange(coins, amount):
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for coin in coins:
for a in range(coin, amount + 1):
dp[a] = min(dp[a], dp[a - coin] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
| Complexity | |
|---|---|
| Time | O(amount × len(coins)) |
| Space | O(amount) |
36. Longest Increasing Subsequence
def lengthOfLIS(nums):
dp = [1] * len(nums)
for i in range(1, len(nums)):
for j in range(i):
if nums[j] < nums[i]:
dp[i] = max(dp[i], dp[j] + 1)
return max(dp)
# O(n log n) with patience sorting
import bisect
def lengthOfLIS(nums):
tails = []
for n in nums:
pos = bisect.bisect_left(tails, n)
if pos == len(tails):
tails.append(n)
else:
tails[pos] = n
return len(tails)
| Approach | Time | Space |
|---|---|---|
| DP | O(n²) | O(n) |
| Binary search | O(n log n) | O(n) |
37. Longest Common Subsequence
def longestCommonSubsequence(text1, text2):
m, n = len(text1), len(text2)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if text1[i - 1] == text2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
return dp[m][n]
| Complexity | |
|---|---|
| Time | O(m · n) |
| Space | O(m · n) → O(min(m, n)) optimised |
38. Word Break
Problem: Can s be segmented into words from dictionary?
def wordBreak(s, wordDict):
word_set = set(wordDict)
dp = [False] * (len(s) + 1)
dp[0] = True
for i in range(1, len(s) + 1):
for j in range(i):
if dp[j] and s[j:i] in word_set:
dp[i] = True
break
return dp[len(s)]
39. House Robber
Problem: Max sum of non-adjacent elements.
def rob(nums):
prev2 = prev1 = 0
for n in nums:
prev2, prev1 = prev1, max(prev1, prev2 + n)
return prev1
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(1) |
40. 0/1 Knapsack
def knapsack(weights, values, capacity):
n = len(weights)
dp = [[0] * (capacity + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
for w in range(capacity + 1):
dp[i][w] = dp[i - 1][w]
if weights[i - 1] <= w:
dp[i][w] = max(dp[i][w],
dp[i - 1][w - weights[i - 1]] + values[i - 1])
return dp[n][capacity]
Greedy
41. Jump Game
Problem: Can you reach the last index?
def canJump(nums):
max_reach = 0
for i, jump in enumerate(nums):
if i > max_reach:
return False
max_reach = max(max_reach, i + jump)
return True
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(1) |
42. Merge Intervals
def merge(intervals):
intervals.sort(key=lambda x: x[0])
merged = [intervals[0]]
for start, end in intervals[1:]:
if start <= merged[-1][1]:
merged[-1][1] = max(merged[-1][1], end)
else:
merged.append([start, end])
return merged
| Complexity | |
|---|---|
| Time | O(n log n) |
| Space | O(n) |
43. Meeting Rooms II (Minimum Rooms)
Problem: Minimum number of conference rooms required.
import heapq
def minMeetingRooms(intervals):
intervals.sort(key=lambda x: x[0])
heap = [] # end times
for start, end in intervals:
if heap and heap[0] <= start:
heapq.heapreplace(heap, end)
else:
heapq.heappush(heap, end)
return len(heap)
44. Task Scheduler
Problem: Minimum intervals needed to execute all tasks (with cooldown n).
from collections import Counter
def leastInterval(tasks, n):
counts = Counter(tasks)
max_count = max(counts.values())
max_count_tasks = sum(1 for c in counts.values() if c == max_count)
result = (max_count - 1) * (n + 1) + max_count_tasks
return max(result, len(tasks))
Bit manipulation
45. Number of 1 Bits
def hammingWeight(n):
count = 0
while n:
count += n & 1
n >>= 1
return count
# Brian Kernighan — clear lowest set bit
def hammingWeight(n):
count = 0
while n:
n &= n - 1
count += 1
return count
46. Counting Bits
Problem: Return array where result[i] = number of 1 bits in i.
def countBits(n):
dp = [0] * (n + 1)
for i in range(1, n + 1):
dp[i] = dp[i >> 1] + (i & 1)
return dp
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(n) |
47. Missing Number
def missingNumber(nums):
n = len(nums)
return n * (n + 1) // 2 - sum(nums)
# XOR approach
def missingNumber(nums):
result = len(nums)
for i, n in enumerate(nums):
result ^= i ^ n
return result
Strings
48. Longest Palindromic Substring
def longestPalindrome(s):
result = ""
for i in range(len(s)):
# Odd length
left, right = i, i
while left >= 0 and right < len(s) and s[left] == s[right]:
if right - left + 1 > len(result):
result = s[left:right + 1]
left -= 1; right += 1
# Even length
left, right = i, i + 1
while left >= 0 and right < len(s) and s[left] == s[right]:
if right - left + 1 > len(result):
result = s[left:right + 1]
left -= 1; right += 1
return result
| Complexity | |
|---|---|
| Time | O(n²) |
| Space | O(1) |
Optimal: Manacher's algorithm — O(n).
49. Encode and Decode Strings
Problem: Encode list of strings to single string, decode back.
class Codec:
def encode(self, strs):
return ''.join(f"{len(s)}#{s}" for s in strs)
def decode(self, s):
result = []
i = 0
while i < len(s):
j = s.index('#', i)
length = int(s[i:j])
result.append(s[j + 1:j + 1 + length])
i = j + 1 + length
return result
Key: Length prefix prevents delimiter ambiguity.
50. Largest Rectangle in Histogram
def largestRectangleArea(heights):
stack = [] # (index, height)
max_area = 0
for i, h in enumerate(heights):
start = i
while stack and stack[-1][1] > h:
idx, height = stack.pop()
max_area = max(max_area, height * (i - idx))
start = idx
stack.append((start, h))
for idx, height in stack:
max_area = max(max_area, height * (len(heights) - idx))
return max_area
| Complexity | |
|---|---|
| Time | O(n) |
| Space | O(n) |
Problem patterns cheat sheet
| Pattern | When to use | Key technique |
|---|---|---|
| Two pointers | Sorted array, palindrome, pairs | Left/right pointers |
| Sliding window | Subarray/substring with constraint | Expand right, shrink left |
| Fast & slow pointers | Cycle detection, middle of list | Different speeds |
| Binary search | Sorted, monotonic function | Eliminate half each step |
| DFS | Tree/graph traversal, backtracking | Recursive or stack |
| BFS | Shortest path, level order | Queue |
| Monotonic stack | Next greater element, histogram | Stack with ordering |
| Prefix sum | Range sum queries | Precompute cumulative sums |
| Union-Find | Connected components | Parent array + find/union |
| Topological sort | DAG ordering, dependencies | DFS or Kahn's BFS |
| Divide & conquer | Sorting, recursion | Split, solve, merge |
| Greedy | Local optimal = global optimal | Sort + scan |
Time complexity at a glance
| Data structure / Algorithm | Average case | Worst case |
|---|---|---|
| Array access | O(1) | O(1) |
| Array search | O(n) | O(n) |
| Hash map get/put | O(1) | O(n) |
| Binary search | O(log n) | O(log n) |
| Merge sort | O(n log n) | O(n log n) |
| Quick sort | O(n log n) | O(n²) |
| BFS / DFS (graph) | O(V + E) | O(V + E) |
| Binary heap insert | O(log n) | O(log n) |
| Binary heap get min | O(1) | O(1) |
Interview approach (step by step)
- Clarify — ask about input constraints, duplicates, null cases
- Examples — walk through 2-3 examples manually
- Brute force — state O(n²) or naive approach first
- Optimise — identify bottleneck, apply pattern
- Code — write clean, modular code
- Test — edge cases: empty, single element, all same, negatives
Common mistakes
| Mistake | Fix |
|---|---|
| Off-by-one in binary search | Use left <= right (search) vs left < right (find boundary) |
| Modifying list while iterating | Iterate copy, or build new list |
| Integer overflow (Java/C++) | Use long, or left + (right - left) // 2 |
| Not handling null node in tree | Always check if not node first |
| Forgetting to mark visited in BFS/DFS | Add to visited set BEFORE enqueuing |
| Two Sum with duplicates | Use index-based hash, not value-based |
| Cycle in linked list causing infinite loop | Use slow/fast pointers or visited set |
| DP not considering all subproblems | Draw the recurrence relation first |
Coding interview vs other interview types
| Interview type | What it tests | Typical duration |
|---|---|---|
| Coding / LeetCode | DS&A, problem-solving | 45-60 min, 1-2 problems |
| System design | Architecture, scalability | 45-60 min |
| Behavioral | Communication, experience | 30-45 min |
| Technical screen | Language, debugging | 30-45 min |
| Take-home | Code quality, testing | 2-8 hours |
Frequently asked questions
How many LeetCode problems should I solve before interviewing? Aim for 100-150 problems covering all major patterns. Quality beats quantity — understand each solution deeply rather than memorising answers. 50 well-understood problems outperform 200 half-remembered ones.
What language should I use in coding interviews? Python is most popular at FAANG — concise, readable, great stdlib. Java/C++ are fine. JavaScript is acceptable but less common. Pick whichever you know best; interviewers care about logic, not language.
What is the most common interview question? Two Sum is the single most asked question. But knowing one pattern (hash map for O(1) lookup) lets you solve dozens of variations.
How long should I spend on a problem before asking for hints? 5-10 minutes of genuine attempt, then state your observations: "I can see this requires O(n) time but I'm stuck on tracking the minimum. Could you confirm my approach direction?"
Do I need to know every algorithm? No. Mastering 10-12 patterns covers 80%+ of interview problems: sliding window, two pointers, DFS/BFS, dynamic programming, binary search, heap, and graph algorithms.
How do I handle a problem I've never seen? Start with brute force, then ask: can I avoid recomputation (DP/memoisation)? Can I use a sorted structure (binary search/heap)? Can I use extra space for O(1) lookup (hash map)?