Top 15 Bloomberg Coding Interview Problems, Ranked by Frequency

- Bloomberg recycles roughly 15 problems across phone screens and onsites; Medium difficulty accounts for 61% of the pipeline, so that is where prep time goes
- LRU Cache (LeetCode 146) is Bloomberg's most common design problem, solved by fusing a doubly linked list and a hash map for O(1) get and put
- Merge Intervals (LeetCode 56) appears in nearly every round; the
max()on the end boundary is the bug candidates most often miss - Communication is scored separately from correctness: a well-explained Medium outscores a silent Hard on Bloomberg's four-dimension rubric
- Bloomberg's follow-up ("Can you do better?") is a scored signal; candidates who optimize proactively rank higher than those who wait to be pushed
- Subarray Sum Equals K (LeetCode 560) trips candidates who reach for sliding window; prefix sums with a hash map are required when the array can contain negatives
Bloomberg pays well. Very well. So people prepare obsessively, and Bloomberg knows it, which is why their interviewers show up to every phone screen holding a scorecard with "communication" on it right next to "correctness." You can grind your way to a working solution and still get a No Hire because you coded it in total silence like a haunted Victorian child.
This list is ordered by frequency across Bloomberg's full pipeline: phone screens, online assessments, and onsites combined. The same problems keep showing up, in slightly different shapes, across hundreds of candidate reports. Limited time? Start at the top and work down.
What Bloomberg's Coding Pipeline Looks Like
| Round | Format | Focus |
|---|---|---|
| Recruiter Screen | 30 min, no code | Background, role fit |
| Technical Phone Screen | 45-60 min | One or two LeetCode Mediums |
| Online Assessment | Async, HackerRank | Two timed problems |
| Onsite Coding (x2) | 45 min each | One Medium or Hard per session |
| System Design | 45-60 min (senior) | Scalability, architecture |
| Behavioral | 30-45 min | Values, collaboration |
The technical phone screen is where most candidates get cut. Bloomberg interviewers score communication separately from correctness. A well-explained Medium scores better than a silent Hard.
Across 400+ reported problems, difficulty splits 28% Easy, 61% Medium, 11% Hard. Medium is where you spend your prep time.
Bloomberg interviewers do not care that you can vibe-code a React app in 20 minutes.
The 15 Bloomberg Coding Interview Problems
1. Two Sum (LeetCode 1), Easy
Category: Hash Map
Bloomberg uses Two Sum as a baseline screen. Not because it is hard, but because it reveals whether you reach for a hash map or write a nested loop and look proud of yourself. The expected solution is O(n). The key insight is that you do not find the second number; you check whether the complement already exists.
def two_sum(nums: list[int], target: int) -> list[int]: seen = {} for i, num in enumerate(nums): complement = target - num if complement in seen: return [seen[complement], i] seen[num] = i return []
Follow-up: "What if the array is sorted?" Two pointers, O(1) space. Have that answer ready. Bloomberg recycles Two Sum partly because it has a neat follow-up ladder that lets interviewers probe how deep your understanding actually goes.
2. Merge Intervals (LeetCode 56), Medium
Category: Sorting + Interval Sweep
One of Bloomberg's highest-frequency problems across all rounds, and it makes total sense once you realize Bloomberg's entire business runs on time-series data, trade execution windows, and schedule conflicts. They are not just testing your coding skills, they are checking whether you can think in the same abstractions their engineers use every day. Sort by start time, then merge whenever the current start falls within the previous end.
def merge(intervals: list[list[int]]) -> list[list[int]]: intervals.sort(key=lambda x: x[0]) result = [intervals[0]] for start, end in intervals[1:]: if start <= result[-1][1]: result[-1][1] = max(result[-1][1], end) else: result.append([start, end]) return result
The max() on the end boundary is not optional. If one interval is entirely contained inside another, skipping it produces wrong output. This is the bug that catches candidates who test only the happy path.
3. LRU Cache (LeetCode 146), Medium
Category: Design (Doubly Linked List + Hash Map)
Bloomberg's most common design problem. The setup sounds innocent enough until you realize no single data structure gives you O(1) lookup and O(1) ordered eviction simultaneously, which is the exact constraint that makes this a design problem rather than a coding problem. A doubly linked list handles order; a hash map handles lookup. Together they achieve O(1) get and put.
Sentinel head and tail nodes eliminate edge cases. Every get moves the accessed node to the tail. Every put that exceeds capacity evicts from the head.
class LRUCache: def __init__(self, capacity: int): self.capacity = capacity self.cache = {} self.head = Node(0, 0) self.tail = Node(0, 0) self.head.next = self.tail self.tail.prev = self.head def get(self, key: int) -> int: if key in self.cache: self._move_to_tail(self.cache[key]) return self.cache[key].val return -1 def put(self, key: int, value: int) -> None: if key in self.cache: self.cache[key].val = value self._move_to_tail(self.cache[key]) else: node = Node(key, value) self.cache[key] = node self._add_to_tail(node) if len(self.cache) > self.capacity: lru = self.head.next self._remove(lru) del self.cache[lru.key]
For the full implementation with _remove and _move_to_tail helpers, see LRU Cache Implementation: Two Data Structures Fused for O(1) Get and Put.
4. Subarray Sum Equals K (LeetCode 560), Medium
Category: Prefix Sum + Hash Map
This appears in Bloomberg phone screens regularly, and it is one of those problems that punishes pattern-matching. It looks exactly like a sliding window problem. It is not. The correct approach uses prefix sums tracked in a hash map: if prefix[j] - prefix[i] == k, the subarray from i+1 to j sums to k. Sliding window breaks the moment the array has negative numbers, which this one does.
def subarray_sum(nums: list[int], k: int) -> int: count = 0 prefix = 0 seen = {0: 1} for num in nums: prefix += num count += seen.get(prefix - k, 0) seen[prefix] = seen.get(prefix, 0) + 1 return count
The {0: 1} initialization handles subarrays starting at index 0. Missing it is the most common bug on this problem. Every candidate who skips it looks confident right up until they run their first test case.
5. Invalid Transactions (LeetCode 1169), Medium
Category: Hash Map + String Parsing
This one is almost offensively Bloomberg-specific. A transaction is invalid if it exceeds $1,000 or occurs in the same city as another transaction from the same person within 60 minutes. The finance domain flavor is not subtle. Group by name, then do pairwise comparison within each group.
from collections import defaultdict def invalid_transactions(transactions: list[str]) -> list[str]: parsed = [] for t in transactions: name, time, amount, city = t.split(',') parsed.append((name, int(time), int(amount), city, t)) grouped = defaultdict(list) for p in parsed: grouped[p[0]].append(p) invalid = set() for group in grouped.values(): for i, (n1, t1, a1, c1, raw1) in enumerate(group): if a1 > 1000: invalid.add(raw1) for _, t2, _, c2, raw2 in group: if c1 != c2 and abs(t1 - t2) <= 60: invalid.add(raw1) invalid.add(raw2) return list(invalid)
Use the raw string as the set key, not a reconstructed version. Duplicate entries in the input are valid and need to stay separate.
6. Decode String (LeetCode 394), Medium
Category: Stack
A string-parsing problem that shows up in Bloomberg phone screens. The nested structure is the tell: any time you see depth or nesting in a problem, a stack is almost certainly involved. Push the current string and repeat count when you see [, then pop and multiply when you see ].
def decode_string(s: str) -> str: stack = [] current_string = "" current_num = 0 for char in s: if char.isdigit(): current_num = current_num * 10 + int(char) elif char == '[': stack.append((current_string, current_num)) current_string, current_num = "", 0 elif char == ']': prev_string, num = stack.pop() current_string = prev_string + num * current_string else: current_string += char return current_string
Multi-digit numbers like 10[a] require accumulation with current_num * 10 + int(char). Candidates who only handle single-digit inputs miss this every time, and then spend five minutes confused about why 10[a] outputs aaaaaaaaaa instead of aaaaaaaaaaaaaaaaaaaaaaaaa.
7. Min Stack (LeetCode 155), Easy
Category: Stack Design
A consistent Bloomberg phone screen warmup. The constraint is O(1) for all operations including getMin, which rules out the "just scan the whole stack" answer that candidates suggest in the first ten seconds. A second stack tracking the minimum at each depth solves this: every push also records the new running minimum.
class MinStack: def __init__(self): self.stack = [] self.min_stack = [] def push(self, val: int) -> None: self.stack.append(val) current_min = min(val, self.min_stack[-1] if self.min_stack else val) self.min_stack.append(current_min) def pop(self) -> None: self.stack.pop() self.min_stack.pop() def top(self) -> int: return self.stack[-1] def getMin(self) -> int: return self.min_stack[-1]
The common mistake: only updating min_stack when you see a new minimum. That breaks on pop because you lose what the minimum was before that push. You need the running minimum at every level, not just when it changes.
8. Insert Delete GetRandom O(1) (LeetCode 380), Medium
Category: Design (Array + Hash Map)
Bloomberg asks this to test whether you understand why random access requires an array index and why O(1) deletion from an arbitrary array position requires a trick. The trick is elegant: instead of deleting mid-array and shifting everything, swap the target element with the last element, update one index in the hash map, and pop from the end. Swap the target element with the last element before deleting; update the displaced element's index in the hash map.
import random class RandomizedSet: def __init__(self): self.indices = {} self.values = [] def insert(self, val: int) -> bool: if val in self.indices: return False self.indices[val] = len(self.values) self.values.append(val) return True def remove(self, val: int) -> bool: if val not in self.indices: return False idx = self.indices[val] last = self.values[-1] self.values[idx] = last self.indices[last] = idx self.values.pop() del self.indices[val] return True def getRandom(self) -> int: return random.choice(self.values)
Edge case: removing the last element. The swap-with-self operation works correctly, but double-check your deletion does not corrupt the index.
9. Best Time to Buy and Sell Stock (LeetCode 121), Easy
Category: Greedy / Single Pass
Bloomberg's most domain-adjacent warmup. You are literally computing max profit from a price series, which is the kind of thing their engineers do before their second cup of coffee. Track the running minimum price and the maximum profit seen so far. Buying at the absolute lowest before the absolute highest is equivalent to a single greedy sweep, no DP needed.
def max_profit(prices: list[int]) -> int: min_price = float('inf') best = 0 for price in prices: min_price = min(min_price, price) best = max(best, price - min_price) return best
Follow-up: "At most 2 transactions?" (LeetCode 123). That one does require DP. Know the distinction before your interviewer makes it for you.
10. Merge K Sorted Lists (LeetCode 23), Hard
Category: Heap
Bloomberg's most common Hard problem. Financial data arrives from multiple feeds simultaneously and needs to be merged in order, which means this problem has real operational stakes for Bloomberg engineers. A min-heap of size K always gives the next smallest element in O(log K). Total complexity is O(N log K) where N is total nodes.
import heapq def merge_k_lists(lists: list) -> object: heap = [] for i, node in enumerate(lists): if node: heapq.heappush(heap, (node.val, i, node)) dummy = ListNode(0) current = dummy while heap: val, i, node = heapq.heappop(heap) current.next = node current = current.next if node.next: heapq.heappush(heap, (node.next.val, i, node.next)) return dummy.next
The i tiebreaker in the tuple prevents comparison errors when two nodes share the same value. Python cannot compare ListNode objects directly, which will produce a very confusing runtime error if you forget this.
11. Trapping Rain Water (LeetCode 42), Hard
Category: Two Pointers
This appears in Bloomberg's second or third onsite coding round. The O(n) DP approach with precomputed max arrays is acceptable and will pass. The two-pointer approach is more impressive because the reasoning is non-obvious: if left_max < right_max, the water level at the left pointer is fully determined by left_max, regardless of what sits to the right. That observation collapses the problem to one pass.
def trap(height: list[int]) -> int: left, right = 0, len(height) - 1 left_max = right_max = water = 0 while left < right: if height[left] < height[right]: if height[left] >= left_max: left_max = height[left] else: water += left_max - height[left] left += 1 else: if height[right] >= right_max: right_max = height[right] else: water += right_max - height[right] right -= 1 return water
The two-pointer approach uses O(1) space vs O(n) for the DP version. If you present the DP solution first, your interviewer will almost certainly ask "can you do it in O(1) space?" Have the answer ready.
12. Number of Islands (LeetCode 200), Medium
Category: Graph BFS/DFS
Bloomberg's most common graph problem in onsite rounds. The setup is straightforward but the implementation has one gotcha that trips people up: you need to mutate the grid as you go, or track visited cells separately. When you find a '1', flood-fill all connected land cells to '0' before counting the next island. This avoids double-counting at zero extra data structure cost.
def num_islands(grid: list[list[str]]) -> int: if not grid: return 0 rows, cols = len(grid), len(grid[0]) count = 0 def dfs(r, c): if r < 0 or r >= rows or c < 0 or c >= cols or grid[r][c] != '1': return grid[r][c] = '0' for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]: dfs(r + dr, c + dc) for r in range(rows): for c in range(cols): if grid[r][c] == '1': dfs(r, c) count += 1 return count
Bloomberg sometimes follows up with connected components in a weighted graph or counting after queries. Know Union-Find as an alternate approach.
13. Product of Array Except Self (LeetCode 238), Medium
Category: Array (Prefix and Suffix Products)
A Bloomberg onsite favorite because it rules out the obvious approach upfront: no division allowed. The constraint is there specifically to force you toward the elegant two-pass solution. Compute prefix products left-to-right into the result array, then multiply by suffix products right-to-left in a second pass. This achieves O(1) extra space.
def product_except_self(nums: list[int]) -> list[int]: n = len(nums) result = [1] * n prefix = 1 for i in range(n): result[i] = prefix prefix *= nums[i] suffix = 1 for i in range(n - 1, -1, -1): result[i] *= suffix suffix *= nums[i] return result
The output array is not counted toward the space bound, so reusing it for prefix products is the expected optimization.
14. Maximum Subarray (LeetCode 53), Medium
Category: Dynamic Programming (Kadane's Algorithm)
A phone screen warm-up that tests whether you know Kadane's algorithm. The algorithm is short enough to fit in your head, which is exactly why Bloomberg uses it to check that you have actually internalized it rather than just seen it once. At each position, either extend the previous subarray or start fresh; whichever is larger. Reset when the running sum goes negative because a negative prefix only hurts what follows.
def max_subarray(nums: list[int]) -> int: current_sum = max_sum = nums[0] for num in nums[1:]: current_sum = max(num, current_sum + num) max_sum = max(max_sum, current_sum) return max_sum
Initialize to nums[0], not 0. All-negative inputs should return the least-negative element. Initializing to 0 produces the wrong answer and is the most reliable way to tell your interviewer that you memorized the template without understanding why it works.
15. Longest Substring Without Repeating Characters (LeetCode 3), Medium
Category: Sliding Window + Hash Map
The clearest sliding window problem in Bloomberg's rotation. The window shrinks from the left whenever a duplicate enters from the right. The one subtlety is the pointer movement: track the last seen index of each character. When you find a duplicate, move the left boundary to max(left, last_seen[char] + 1). The max prevents jumping the left pointer backward into territory already processed.
def length_of_longest_substring(s: str) -> int: last_seen = {} left = max_length = 0 for right, char in enumerate(s): if char in last_seen and last_seen[char] >= left: left = last_seen[char] + 1 last_seen[char] = right max_length = max(max_length, right - left + 1) return max_length
The last_seen[char] >= left guard is what distinguishes a correct solution from an almost-correct one. Without it, you can move left backward when the same character appeared before the current window.
How Bloomberg Actually Scores Coding Rounds
Here is the part that catches people off guard: Bloomberg's scorecard has four dimensions, and "correctness" is only one of them. Candidates who solve the problem but code in total silence frequently receive a No Hire despite a working solution. The interviewer has a rubric to fill out and silence leaves most of the boxes empty.
The four dimensions:
- Correctness: Right output, including edge cases you catch yourself before being told
- Efficiency: Can you reason about time and space? Do you know when your solution is suboptimal and articulate why?
- Communication: Do you explain your approach before writing code? Do you narrate tricky decisions?
- Code quality: Readable, no dead code, reasonable variable names
The single biggest Bloomberg signal is how you respond to the follow-up. Bloomberg interviewers almost always push with "Can you do better?" or introduce a constraint change mid-problem. Candidates who optimize proactively score higher than those who only move after being pushed.
Solving the problem in silence is the resume.pdf move. Talk through your reasoning as you go.
Your 3-Week Prep Plan
| Week | Focus | Problems |
|---|---|---|
| 1 | Hash maps, arrays, greedy | 1, 4, 9, 13, 14 |
| 2 | Stack, design, intervals | 2, 3, 6, 7, 8 |
| 3 | Graphs, heap, Hard problems | 5, 10, 11, 12, 15 |
Practice narrating out loud. Bloomberg interviewers score your reasoning as you go, not just the final answer. SpaceComplexity runs voice-based mock interviews with rubric-based feedback on communication and solution quality, the gap this list leaves open.
Before your phone screen, solve problems 1 through 8 in under 20 minutes each. The onsite rounds go to the harder half.
For the full round-by-round breakdown of Bloomberg's pipeline, see Bloomberg Software Engineer Interview: Rounds, DSA, and Offers and Bloomberg Phone Screen: What It Covers, How It's Scored, and How to Pass.
Further Reading
- Bloomberg Careers Engineering, official Bloomberg engineering culture page
- LeetCode Bloomberg Company Page, full company-tagged problem set
- Wikipedia: Cache Replacement Policies, formal LRU and LFU definitions
- Wikipedia: Maximum Subarray Problem, Kadane's algorithm derivation
- Glassdoor Bloomberg Software Engineer Interviews, candidate-reported questions and difficulty ratings