Atlassian 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 Atlassian hiring for Data Structures and Algorithms roles
Atlassian builds team collaboration and software development tools such as Jira, Confluence, Trello, Bitbucket and Jira Service Management. It runs a significant engineering team in Bengaluru and follows a distributed work policy. Hiring in India covers software engineers, quality and reliability engineers, data engineers and data scientists who work on product analytics and platform features.
For Data Structures and Algorithms roles, this Atlassian practice set focuses most on Graphs and Graph Algorithms (6), Arrays, Strings and Hashing (5), Linked Lists, Stacks and Queues (4), Complexity Analysis and Recursion (4). It has 22 medium, 8 hard questions, so you can start easy and work up to the harder ones.
Company type
Product
Headquarters
Sydney, Australia
Main India offices
Bengaluru
Atlassian Data Structures and Algorithms interview process
Online coding assessment
Coding round
System design or data round
Values round
Hiring manager round
Typical pattern based on public candidate experiences. Rounds vary by role, team and year.
Solved for AtlassianStart 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
How can you implement a queue using two stacks, and what is its complexity?
Use an in-stack for enqueue and an out-stack for dequeue. Enqueue pushes onto the in-stack in O(1). For dequeue, if the out-stack is empty, pop everything from the in-stack and push it onto the out-stack, which reverses the order, then pop from the out-stack. Each element moves at most once between stacks, so dequeue is O(1) amortised even though a single transfer can be O(n).
02
Detect whether a linked list has a cycle and return the node where the cycle begins.
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
Implement topological sort using Kahn's algorithm.
from collections import deque
def topo_sort(n, edges):
adj = [[] for _ in range(n)]
indeg = [0] * n
for u, v in edges: # u must come before v
adj[u].append(v)
indeg[v] += 1
q = deque(i for i in range(n) if indeg[i] == 0)
order = []
while q:
u = q.popleft()
order.append(u)
for v in adj[u]:
indeg[v] -= 1
if indeg[v] == 0:
q.append(v)
return order if len(order) == n else [] # empty means a cycle exists
04
You have a 100 GB file of integers and only 4 GB of RAM. How would you find the duplicates?
The data does not fit in memory, so I would partition it. Read the file in streaming fashion and write each number to one of, say, 50 bucket files based on hash of the number modulo 50, so equal numbers land in the same bucket. Each bucket of about 2 GB fits in memory, where a hash set finds duplicates. Alternatively use external merge sort and scan adjacent values. A Bloom filter can pre-screen candidates.
05
Your brute-force solution for the longest substring without repeating characters is O(n cubed). How would you improve it?
I would use a variable sliding window. Keep a map from character to its last index and a left pointer. Move the right pointer through the string; when the current character was seen at an index at or after left, move left to that index plus one. Update the best length at each step. Each character is processed a constant number of times, giving O(n) time and O(alphabet size) space.
06
An interviewer asks you to reduce your solution's extra space from O(n) to O(1). How do you approach it?
I check what the extra structure stores and whether the input itself can hold that information. Common techniques: use two pointers instead of a hash set on sorted data, keep only the last few DP values instead of a full table, modify the input in place, such as marking visited indices by negating values, or use bit manipulation like XOR to find a missing number. I state any trade-offs, such as mutating input.
07
Compare Kruskal's and Prim's algorithms for minimum spanning trees.
Both find a minimum spanning tree, the cheapest set of edges connecting all vertices. Kruskal sorts all edges by weight and adds each edge if it joins two different components, checked with Union-Find, O(E log E); it suits sparse graphs given as edge lists. Prim grows the tree from a start vertex, always adding the cheapest edge leaving the tree using a min-heap, O(E log V), which suits dense graphs with adjacency lists.
08
A hash map lookup in your service suddenly becomes very slow under certain traffic. What could cause it?
If many keys produce the same hash, they pile into a few buckets and operations degrade toward O(n). This can come from a poor custom hashCode, such as returning a constant or using only one field, or from attackers sending crafted keys. Fixes include a better hash function combining all fields, randomised hashing, which Python uses for strings, and tree-based buckets as in Java 8 HashMap, which caps the worst case at O(log n).
09
Design a simple scheduler that gives each job a fixed time slice in turn.
Round-robin scheduling fits a queue. Put all jobs in a FIFO queue. Repeatedly dequeue a job, run it for one time slice, and if it is not finished, enqueue it at the back with its remaining time. Each step is O(1). For priorities, keep one queue per priority level or use a priority queue. A circular buffer works well if the number of jobs is bounded, avoiding allocations.
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
11
Serialize a binary tree to a string and deserialize it back.
def length_of_longest_substring(s):
last = {} # char -> last index seen
left = best = 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
# 'abcabcbb' -> 3, 'bbbbb' -> 1, 'pwwkew' -> 3; O(n) time
13
Packages with given weights must be shipped in order within D days. How do you find the minimum ship capacity?
The capacity lies between the heaviest package and the total weight, and if a capacity works, any larger one also works, so binary search the answer. For a candidate capacity, greedily load packages day by day, starting a new day when the next package does not fit, and count days. If the days are within D, try smaller; otherwise try larger. Time is O(n log of total weight).
14
Generate all subsets of a list of distinct numbers.
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
15
Implement Dijkstra's algorithm with a priority queue.
Model services as a directed graph and run DFS with three colours. When DFS reaches a node that is still on the current stack, it has found a back edge, and walking the parent pointers from the current node back to that node gives the exact cycle to report, such as A to B to C to A. Running this check in CI before every build prevents the problem, and Kahn's algorithm can list all nodes involved.
17
You must build autocomplete for a search box over one million product names. Which data structure would you use?
I would use a trie where each node stores, besides children, the top few most popular completions under that prefix. Then typing a prefix walks L nodes and returns precomputed suggestions instantly, without exploring the whole subtree. Memory can be reduced with a compressed radix trie. For typo tolerance or ranking by many signals, a search engine with prefix indexes is more practical at large scale.
18
What is the time complexity of an outer loop from 0 to n with an inner loop where j starts at 1 and doubles until it reaches n?
The outer loop runs n times. In the inner loop j takes values 1, 2, 4, 8 and so on until it reaches n, which is about log base 2 of n iterations. Because the inner loop does not depend on the outer index, the total is n times log n, so the complexity is O(n log n). If instead the inner loop ran from 0 to i, the total would be n squared over 2, which is O(n squared).
19
Find the lowest common ancestor of two nodes in a binary tree.
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
20
What are lower bound and upper bound, and what common bugs appear in binary search?
Lower bound returns the first index whose value is not less than the target, and upper bound the first index whose value is greater, so their difference counts occurrences. Common bugs are off-by-one errors in the loop condition, infinite loops when mid does not move, and integer overflow from (low plus high) divided by 2 in Java or C++; use low plus (high minus low) divided by 2. Python's bisect module provides both functions.
21
Implement Union-Find with path compression and union by size.
Keep a second stack of minimums. On push, push the value onto the main stack and push the smaller of the value and the current minimum onto the min stack. On pop, pop both. getMin returns the top of the min stack in O(1). To save space, push onto the min stack only when the new value is less than or equal to the current minimum, and pop it only when the popped value equals it.
24
An application needs sorted data with frequent inserts, deletes and range queries such as all orders between two timestamps. Which structure fits?
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.
25
Find the minimum number of coins needed to make an amount.
def coin_change(coins, amount):
INF = amount + 1
dp = [0] + [INF] * amount # dp[x] = min coins for amount x
for x in range(1, amount + 1):
for c in coins:
if c <= x and dp[x - c] + 1 < dp[x]:
dp[x] = dp[x - c] + 1
return dp[amount] if dp[amount] != INF else -1
# coin_change([1, 3, 4], 6) -> 2 (3 + 3)
# O(amount * len(coins)) time, O(amount) space
26
How can you reduce the space used by a DP solution?
If each row of the table depends only on the previous row, keep two rows or even a single array, reducing O(n times m) space to O(m). Fibonacci-like problems need only the last two values, so O(1). For 0/1 knapsack in one array, iterate capacity from high to low so each item is used once; for unbounded knapsack iterate low to high. The trade-off is that reconstructing the actual solution becomes harder.
27
A network has 10 million devices and connections are added continuously. You must answer whether two devices are connected in real time. How?
Running BFS for every query is too slow. Since connections are only added, Union-Find is ideal: each new link is a union, and each query compares find results, both nearly O(1) amortised with path compression and union by size. Memory is two integer arrays of 10 million entries, about 80 MB. If links can also be removed, the problem becomes much harder and needs offline processing or specialised dynamic connectivity structures.
28
A company has a fixed budget and several projects with costs and expected returns. How would you choose projects to maximise return?
If each project is all or nothing, this is the 0/1 knapsack problem: budget is capacity, cost is weight and return is value, solved with DP in O(projects times budget), and tracking choices lets me list selected projects. If the budget is very large, I would scale costs to units such as lakhs to keep the table small, or use DP over value instead. Extra constraints like dependencies change the state design.
29
How do the KMP and Rabin-Karp string matching algorithms work?
Naive matching is O(n times m). KMP precomputes a longest prefix-suffix array for the pattern, so after a mismatch it shifts the pattern without re-reading text characters, giving O(n plus m) worst case. Rabin-Karp computes a rolling hash of each text window and compares characters only when hashes match, averaging O(n plus m) and extending well to multiple patterns, but collisions can make the worst case O(n times m).
30
A recursive DFS in Python crashes with RecursionError on a deep input. How do you fix it?
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.
Tips to crack the Atlassian Data Structures and Algorithms interview
Read Atlassian's company values, such as Don't #@!% the Customer and Open Company, No Bullshit, for the values interview.
Use Jira and Confluence hands-on so you can discuss workflows, agile boards and possible product improvements.
Practise writing clean, well-structured code, as Atlassian coding rounds often value code quality and testing, not just correctness.
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; Atlassian interviewers usually ask follow-ups on your first answer.
Frequently asked questions
How many rounds are there in the Atlassian Data Structures and Algorithms interview?
Candidates usually go through 5 stages: Online coding assessment; Coding round; System design or data round; Values round; Hiring manager 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 Atlassian Data Structures and Algorithms interview?
This practice set leans on Graphs and Graph Algorithms (6), Arrays, Strings and Hashing (5), Linked Lists, Stacks and Queues (4), Complexity Analysis and Recursion (4). Revise those first, then practise explaining one or two of your own projects end to end, because most Atlassian interviewers ask you to walk through real work.
Are these the exact questions asked at Atlassian?
No. These are curated practice questions that match the skills and difficulty usually tested in product interviews like Atlassian's. They are not a leaked or verified list of past questions.
Where does Atlassian hire Data Structures and Algorithms professionals in India?
Atlassian has large teams in Bengaluru. Openings and locations change often, so check the Atlassian careers page and filter by city and experience.
Data Structures and Algorithms questions for similar companies