Skip to content

Adobe Data Structures and Algorithms Interview Questions & Answers

Curated interview practice questions with answers. These are practice scenarios, not a verified list of past interview questions.

About Adobe hiring for Data Structures and Algorithms roles

Adobe makes creative, document and marketing software including Photoshop, Acrobat, Premiere Pro, Adobe Express and Adobe Experience Cloud. Its Noida and Bengaluru centres are among its largest engineering sites globally. It hires in India for software engineers, quality engineers, data scientists and analysts working on product analytics, marketing data and AI features such as Firefly.

For Data Structures and Algorithms roles, this Adobe practice set focuses most on Graphs and Graph Algorithms (5), Trees and Binary Search Trees (5), Sorting, Searching and Backtracking (4), Dynamic Programming (4). It has 22 medium, 8 hard questions, so you can start easy and work up to the harder ones.

Company type
Product
Headquarters
San Jose, California, USA
Main India offices
Noida, Bengaluru, Gurugram

Adobe Data Structures and Algorithms interview process

  1. Online assessment (aptitude + coding)
  2. Technical round 1 (DSA)
  3. Technical round 2 (DSA + CS fundamentals)
  4. Hiring manager round
  5. HR round

Typical pattern based on public candidate experiences. Rounds vary by role, team and year.

Solved for AdobeStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

A sorted array has been rotated at an unknown point. How can you still search it in O(log n)?

Save to ▾
Show answer
At every step of binary search, at least one half around mid is sorted. Compare nums[low] with nums[mid]: if the left half is sorted and the target lies within its range, search left, otherwise search right. If the right half is sorted, apply the same check on the right. This keeps O(log n). With duplicates allowed, equal values can hide which half is sorted, and the worst case becomes O(n).
02

Detect whether a linked list has a cycle and return the node where the cycle begins.

Save to ▾
Show answer
def detect_cycle(head): slow = fast = head while fast and fast.next: slow = slow.next fast = fast.next.next if slow is fast: # cycle found slow = head while slow is not fast: # move both one step slow = slow.next fast = fast.next return slow # start of the cycle return None # O(n) time, O(1) space
03

How does Floyd's cycle detection algorithm work and why is it correct?

Save to ▾
Show answer
Floyd uses a slow pointer moving one step and a fast pointer moving two steps. If there is no cycle, fast reaches the end. If there is a cycle, fast gains one step per iteration on slow inside the loop, so they must meet. To find the cycle start, reset one pointer to the head and move both one step at a time; they meet at the start because the distances from head and from the meeting point are equal modulo the cycle length.
04

You must merge two sorted arrays where the first array has enough empty space at the end for the second. How would you do it in place?

Save to ▾
Show answer
Merging from the front would overwrite unread elements, so merge from the back. Use three pointers: the last real element of the first array, the last element of the second, and the last slot of the first array. Repeatedly place the larger of the two candidates at the write position and move pointers left. When the second array is exhausted, the rest is already in place. This takes O(m plus n) time and O(1) space.
05

What is topological sorting and how is it done?

Save to ▾
Show answer
A topological order lists the vertices of a DAG so every edge goes from earlier to later, such as an order to take courses. Kahn's algorithm computes in-degrees, pushes zero in-degree vertices into a queue and repeatedly removes them while decreasing neighbours' in-degrees; if not all vertices are output, a cycle exists. The DFS method adds a vertex to a list after visiting its descendants and reverses the list. Both are O(V plus E).
06

Compute the edit distance between two words.

Save to ▾
Show answer
def edit_distance(a, b): m, n = len(a), len(b) prev = list(range(n + 1)) # distances from empty prefix of a for i in range(1, m + 1): cur = [i] + [0] * n for j in range(1, n + 1): if a[i - 1] == b[j - 1]: cur[j] = prev[j - 1] else: cur[j] = 1 + min(prev[j], # delete cur[j - 1], # insert prev[j - 1]) # replace prev = cur return prev[n] # edit_distance('horse', 'ros') -> 3; O(m * n) time, O(n) space
07

Return an array where each element is the product of all other elements, without using division.

Save to ▾
Show answer
def product_except_self(nums): n = len(nums) out = [1] * n prefix = 1 for i in range(n): # product of everything to the left out[i] = prefix prefix *= nums[i] suffix = 1 for i in range(n - 1, -1, -1): # multiply by everything to the right out[i] *= suffix suffix *= nums[i] return out # [1,2,3,4] -> [24,12,8,6]; O(n) time, O(1) extra space besides output
08

How do you prioritise when several tasks have deadlines at the same time?

Save to ▾
Show answer
Situation: in one sprint I had a bug fix, a feature and interview preparation for a new hire panel all due together. Task: deliver without dropping quality. Action: I listed the tasks with impact and deadline, discussed the order with my lead, finished the customer-facing bug first, split the feature into smaller deliverables and blocked calendar time for each. Result: everything was delivered within the week and nothing urgent slipped.
09

Find the lowest common ancestor of two nodes in a binary tree.

Save to ▾
Show answer
def lca(root, p, q): if root is None or root is p or root is q: return root left = lca(root.left, p, q) right = lca(root.right, p, q) if left and right: # p and q are on different sides return root return left or right # O(n) time, O(h) space; assumes both nodes exist in the tree
10

How can two heaps maintain the running median of a stream?

Save to ▾
Show answer
Keep a max-heap for the smaller half of the numbers and a min-heap for the larger half, balanced so their sizes differ by at most one. Insert each number into the correct heap, then move the top element across if sizes become unbalanced. The median is the top of the larger heap, or the average of both tops when sizes are equal. Insertion is O(log n) and finding the median is O(1).
11
Save to ▾
Show answer
def merge_sort(a): if len(a) <= 1: return a mid = len(a) // 2 left = merge_sort(a[:mid]) right = merge_sort(a[mid:]) out, i, j = [], 0, 0 while i < len(left) and j < len(right): if left[i] <= right[j]: # <= keeps the sort stable out.append(left[i]); i += 1 else: out.append(right[j]); j += 1 out.extend(left[i:]) out.extend(right[j:]) return out # O(n log n) time, O(n) extra space
12

An application needs sorted data with frequent inserts, deletes and range queries such as all orders between two timestamps. Which structure fits?

Save to ▾
Show answer
A balanced BST, such as Java TreeMap or a sorted container in Python, gives O(log n) insert and delete and O(log n plus k) range queries using floor, ceiling or subMap operations. A sorted array has fast range queries but O(n) inserts, and a hash map cannot do ranges at all. If the data lives in a database, a B-tree index on the timestamp column solves the same problem.
13

How would you generate friend suggestions as friends of friends in a social network?

Save to ▾
Show answer
Run a BFS limited to depth 2 from the user. For every friend, look at their friends, skip the user and existing friends, and count how many mutual friends each candidate has using a hash map. Rank candidates by mutual friend count and other signals. For users with thousands of friends this gets expensive, so production systems precompute suggestions offline in batch jobs and cache them.
14

A recursive DFS in Python crashes with RecursionError on a deep input. How do you fix it?

Save to ▾
Show answer
CPython limits recursion depth to about 1000 by default. Raising the limit with sys.setrecursionlimit works for moderate depth but can crash the interpreter on very deep inputs because the C stack is limited. The reliable fix is to rewrite the DFS iteratively with an explicit stack, pushing nodes and processing them in a loop. In Java the same issue appears as StackOverflowError and has the same solution.
15

Tell me about a time you explained a technical idea to a non-technical person.

Save to ▾
Show answer
Situation: a product manager asked why a search feature became slow as data grew. Task: explain the cause and the fix without jargon. Action: I compared the current approach to checking every book in a library one by one and the fix to using the catalogue index, then showed a simple chart of response times before and after a prototype. Result: the manager approved two sprints for the change and later reused my analogy with clients.
16

Rotate an array to the right by k steps in place.

Save to ▾
Show answer
def rotate(nums, k): n = len(nums) k %= n def reverse(l, r): while l < r: nums[l], nums[r] = nums[r], nums[l] l += 1 r -= 1 reverse(0, n - 1) # reverse all reverse(0, k - 1) # reverse first k reverse(k, n - 1) # reverse the rest # [1,2,3,4,5,6,7], k=3 -> [5,6,7,1,2,3,4]; O(n) time, O(1) space
17

Your knapsack DP has n equal to 100 items but capacity up to 10 to the power 9, so the table does not fit in memory. What do you do?

Save to ▾
Show answer
A table indexed by capacity is impossible, so I change the state. If item values are small, use dp[v] as the minimum weight needed to achieve value v, then pick the largest v whose weight fits the capacity; that is O(n times total value). If n is about 40, meet in the middle: enumerate subsets of each half, sort one side and binary search. Otherwise approximation or branch and bound are options.
18

Write a function to validate a binary search tree.

Save to ▾
Show answer
def is_valid_bst(root, low=float('-inf'), high=float('inf')): if not root: return True if not (low < root.val < high): return False return (is_valid_bst(root.left, low, root.val) and is_valid_bst(root.right, root.val, high)) # Passing bounds checks the whole-subtree property, not just children. # O(n) time, O(h) space.
19

You can use an O(n log n) algorithm with high constant factors or a simple O(n squared) one. For what inputs might the O(n squared) choice be better?

Save to ▾
Show answer
Big-O ignores constants, so for small n the simpler algorithm can be faster in practice. Insertion sort beats merge sort for arrays below roughly 16 to 32 elements, which is why library sorts such as Timsort switch to insertion sort for small runs. I would benchmark on realistic input sizes, choose the asymptotically better algorithm when n can grow, and use a hybrid when both ranges occur.
20

Tell me about a time you worked with people from other teams to solve a complex problem.

Save to ▾
Show answer
Situation: delivery route suggestions in our app were slow and the data team blamed the backend while we blamed the data. Task: find the real issue. Action: I set up a joint session, we traced one slow request end to end and found the graph was rebuilt from raw tables on every call. I proposed caching the adjacency lists, and the data team added change notifications. Result: response time dropped from 3 seconds to 200 milliseconds.
21

What is the diameter of a binary tree and how do you compute it efficiently?

Save to ▾
Show answer
The diameter is the number of edges on the longest path between any two nodes, which may not pass through the root. Compute it in one postorder traversal: for each node, get the heights of the left and right subtrees, update a global best with left plus right, and return 1 plus the larger height to the parent. This visits each node once, giving O(n) time instead of O(n squared) from recomputing heights.
22

A game leaderboard with millions of players needs fast score updates and queries like what rank is this player. How would you design it?

Save to ▾
Show answer
Sorting on every query is too slow. I would bucket scores and use a Fenwick tree or segment tree over score values, storing how many players have each score; a player's rank is the count of players with higher scores, found in O(log S). Updates move a player between buckets in O(log S). An order-statistic balanced tree also works, and in production Redis sorted sets, built on skip lists, provide this directly.
23

Find the shortest path length from the top-left to the bottom-right of a grid where 1 is a wall.

Save to ▾
Show answer
from collections import deque def shortest_path(grid): R, C = len(grid), len(grid[0]) if grid[0][0] or grid[R-1][C-1]: return -1 q = deque([(0, 0, 1)]) seen = {(0, 0)} while q: r, c, d = q.popleft() if (r, c) == (R - 1, C - 1): return d for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)): nr, nc = r + dr, c + dc if 0 <= nr < R and 0 <= nc < C and not grid[nr][nc] and (nr, nc) not in seen: seen.add((nr, nc)) q.append((nr, nc, d + 1)) return -1 # BFS: O(R * C)
24

How is the longest common subsequence computed with DP?

Save to ▾
Show answer
Let dp[i][j] be the LCS length of the first i characters of A and the first j characters of B. If A[i-1] equals B[j-1], dp[i][j] is dp[i-1][j-1] plus 1; otherwise it is the maximum of dp[i-1][j] and dp[i][j-1]. Fill the table row by row in O(m times n) time. Backtracking from dp[m][n] recovers the actual subsequence. LCS underlies diff tools and DNA sequence comparison.
25

A Sudoku solver using plain backtracking is too slow on hard puzzles. How would you speed it up?

Save to ▾
Show answer
Add stronger pruning and better choice ordering. Keep bitmasks of used digits for each row, column and box, so validity checks are O(1). Always fill the empty cell with the fewest candidates first, the minimum remaining values heuristic, which shrinks the search tree dramatically. Apply constraint propagation, filling cells with a single candidate before guessing. For the hardest cases, exact cover with Dancing Links is very fast.
26

Search for a target in a rotated sorted array.

Save to ▾
Show answer
def search_rotated(nums, target): lo, hi = 0, len(nums) - 1 while lo <= hi: mid = (lo + hi) // 2 if nums[mid] == target: return mid if nums[lo] <= nums[mid]: # left half sorted if nums[lo] <= target < nums[mid]: hi = mid - 1 else: lo = mid + 1 else: # right half sorted if nums[mid] < target <= nums[hi]: lo = mid + 1 else: hi = mid - 1 return -1 # [4,5,6,7,0,1,2], 0 -> 4; O(log n)
27

You need to merge K sorted log files from different servers into one sorted output. How would you do it efficiently?

Save to ▾
Show answer
Use a min-heap of size K holding the current smallest line from each file, keyed by timestamp. Pop the smallest, write it out, and push the next line from the same file. Each line is pushed and popped once, so total time is O(N log K) for N lines, and memory is O(K) plus buffers, which works even when files are larger than RAM. Buffered reading and writing keeps I/O efficient.
28

Generate all subsets of a list of distinct numbers.

Save to ▾
Show answer
def subsets(nums): result = [] current = [] def backtrack(i): if i == len(nums): result.append(current[:]) return current.append(nums[i]) # include nums[i] backtrack(i + 1) current.pop() # exclude nums[i] backtrack(i + 1) backtrack(0) return result # 2^n subsets, each up to n long: O(n * 2^n) time
29

How do you handle disagreement with a reviewer about your solution in a code review?

Save to ▾
Show answer
Situation: a reviewer wanted me to replace my BFS solution with a more complex bidirectional search. Task: reach the best decision for the code, not win the argument. Action: I asked about their concern, which was latency on large graphs, then shared measurements showing our graphs were small and the simpler code was faster to maintain, and agreed to add a benchmark that would alert us if size grew. Result: the reviewer approved and we documented the trade-off.
30

A search box must suggest the closest dictionary words when a user makes a typo. How would you approach it?

Save to ▾
Show answer
Compute edit distance between the typed word and candidate words, suggesting those within distance 1 or 2. Running O(m times n) DP against a whole dictionary is slow, so narrow candidates first using a BK-tree indexed by edit distance, a trie with bounded edit distance search, or n-gram indexes. Then rank candidates by distance and word popularity. Keyboard-aware substitution costs can improve suggestions further.

Tips to crack the Adobe Data Structures and Algorithms interview

  • Practise DSA and puzzles, which have commonly appeared in Adobe interviews alongside OOP and operating system questions.
  • Use Adobe Acrobat or Express and be ready to suggest a feature or test plan for one of its products.
  • For data roles, read about Adobe Analytics and Experience Platform, since many teams work on customer and marketing data.
  • Keep a one-minute story ready for every project on your CV: problem, your part, tools, result.
  • Practise the hard questions on this page aloud; Adobe interviewers usually ask follow-ups on your first answer.

Frequently asked questions

How many rounds are there in the Adobe Data Structures and Algorithms interview?

Candidates usually go through 5 stages: Online assessment (aptitude + coding); Technical round 1 (DSA); Technical round 2 (DSA + CS fundamentals); Hiring manager round; HR round. The exact rounds change with the role, team, location and your experience, so confirm the process with the recruiter.

Which topics should I prepare for the Adobe Data Structures and Algorithms interview?

This practice set leans on Graphs and Graph Algorithms (5), Trees and Binary Search Trees (5), Sorting, Searching and Backtracking (4), Dynamic Programming (4). Revise those first, then practise explaining one or two of your own projects end to end, because most Adobe interviewers ask you to walk through real work.

Are these the exact questions asked at Adobe?

No. These are curated practice questions that match the skills and difficulty usually tested in product interviews like Adobe's. They are not a leaked or verified list of past questions.

Where does Adobe hire Data Structures and Algorithms professionals in India?

Adobe has large teams in Noida, Bengaluru, Gurugram. Openings and locations change often, so check the Adobe careers page and filter by city and experience.

Data Structures and Algorithms questions for similar companies