Uber's engineering interview has a recognizable flavor: alongside standard data-structures-and-algorithms, you'll often get an object-oriented design problem and at least one graph problem that echoes Uber's real domain — routing, dispatch, surge zones. The interviewers tend to reward clean, extensible code over clever one-liners.
This guide covers five representative Uber problems with worked Python, the full loop, and the design-thinking habits that separate a hire from a no-hire when the question is deliberately open-ended.
The full interview process
| Stage | Format | Notes |
|---|---|---|
| Recruiter screen | 30 min | Background, level, logistics |
| Technical phone screen | 45-60 min | 1-2 DS&A problems on CoderPad |
| Onsite coding (2) | 45 min each | DS&A plus an OOD-flavored problem |
| Graph / domain round | 45 min | Routing, grids, or scheduling |
| System design (mid/senior) | 45 min | Design a real-world Uber-scale service |
| Behavioral / hiring manager | 45 min | Ownership, collaboration, team fit |
Problem 1: Course Schedule (topological sort)
Question: There are numCourses labeled 0..n-1 and prerequisite pairs. Return true if you can finish all courses (i.e., the dependency graph has no cycle).
Cycle detection on a directed graph via Kahn's algorithm: repeatedly remove nodes with in-degree zero; if you can remove all of them, there's no cycle.
from collections import deque, defaultdict
def canFinish(numCourses, prerequisites):
graph = defaultdict(list)
indegree = [0] * numCourses
for course, pre in prerequisites:
graph[pre].append(course)
indegree[course] += 1
queue = deque([i for i in range(numCourses) if indegree[i] == 0])
seen = 0
while queue:
node = queue.popleft()
seen += 1
for nxt in graph[node]:
indegree[nxt] -= 1
if indegree[nxt] == 0:
queue.append(nxt)
return seen == numCourses
Time O(V+E), space O(V+E). Topological sort is a staple at Uber because dependency/ordering shows up everywhere in their systems. State whether you'd return the ordering itself (Course Schedule II) if asked.
Follow-up: "Return one valid course order." Collect nodes as you pop them; if the collected list has length numCourses, it's a valid topological order.
Problem 2: LRU Cache (object-oriented design)
Question: Design a data structure for a Least-Recently-Used cache with O(1) get and put.
The canonical OOD problem — and a favorite at Uber. Combine a hash map (key → node) with a doubly linked list (recency order). Python's OrderedDict gives both, but be ready to build it from scratch.
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity):
self.cache = OrderedDict()
self.cap = capacity
def get(self, key):
if key not in self.cache:
return -1
self.cache.move_to_end(key)
return self.cache[key]
def put(self, key, value):
if key in self.cache:
self.cache.move_to_end(key)
self.cache[key] = value
if len(self.cache) > self.cap:
self.cache.popitem(last=False)
Both operations are O(1). If the interviewer asks you to implement the linked list manually (common at Uber to test fundamentals), maintain head/tail sentinels and splice nodes on access. Narrate the invariant: most-recent at the tail, least-recent at the head.
Problem 3: Word Ladder (BFS shortest path)
Question: Given beginWord, endWord, and a word list, return the length of the shortest transformation sequence changing one letter at a time, where each intermediate word is in the list.
Shortest path on an implicit graph — BFS level by level. Generate neighbors by changing each character to a-z and checking the word set.
from collections import deque
def ladderLength(beginWord, endWord, wordList):
words = set(wordList)
if endWord not in words: return 0
queue = deque([(beginWord, 1)])
while queue:
word, steps = queue.popleft()
if word == endWord:
return steps
for i in range(len(word)):
for c in 'abcdefghijklmnopqrstuvwxyz':
nxt = word[:i] + c + word[i+1:]
if nxt in words:
words.remove(nxt)
queue.append((nxt, steps + 1))
return 0
BFS guarantees the first time you reach endWord is the shortest path. Removing words from the set as you enqueue them prevents revisits. Time is O(N×L×26) where L is word length.
Problem 4: Trapping Rain Water (two pointers)
Question: Given an array of bar heights, compute how much water it can trap after raining.
Each position holds water equal to min(maxLeft, maxRight) minus its own height. The O(n) trick is two pointers moving inward, advancing the side with the smaller running max.
def trap(height):
left, right = 0, len(height) - 1
left_max = right_max = 0
water = 0
while left < right:
if height[left] < height[right]:
left_max = max(left_max, height[left])
water += left_max - height[left]
left += 1
else:
right_max = max(right_max, height[right])
water += right_max - height[right]
right -= 1
return water
Time O(n), space O(1). The insight that makes it click: if height[left] < height[right], the water at left is bounded by left_max regardless of what's on the right. Walk the interviewer through that argument.
Patterns Uber asks most
| Pattern | Frequency | Note |
|---|---|---|
| Graphs (BFS/DFS, topo sort) | ~30% of loops | Routing and dependency themes |
| Object-oriented design | ~20% | LRU, rate limiter, parking lot |
| Two pointers / sliding window | ~15% | Arrays and strings |
| Heap / intervals | ~15% | Merge intervals, k-closest drivers |
| Hash map design | ~10% | Frequency, grouping, caching |
| Dynamic programming | ~10% | Less common than at Google |
Common pitfalls specific to Uber
- Writing throwaway code on the OOD round. Uber grades extensibility. Use clear class boundaries and name methods as if a teammate will extend them next week.
- Missing the graph framing. Many Uber problems are graphs in disguise (routing, scheduling). If you see nodes-and-edges structure, say so explicitly.
- Ignoring scale assumptions. Ask about input size early — Uber problems sometimes imply millions of drivers, which changes whether a brute force is acceptable.
- Forgetting concurrency in design rounds. For caches and rate limiters, mention thread-safety even if you don't fully implement it.
A 4-week prep plan for an Uber loop
- Week 1: Graph fundamentals — BFS, DFS, topological sort, Dijkstra. Solve 15 graph problems.
- Week 2: Object-oriented design — LRU cache, rate limiter, parking lot, in-memory key-value store. Practice from scratch, not with library shortcuts.
- Week 3: Mixed mediums plus the system design cheat sheet for the design round.
- Week 4: Behavioral stories on ownership and cross-team collaboration, plus a live-coding rehearsal.
Stay clean and extensible with live AI support
CoPilot Interview surfaces structured solutions in about 4 seconds during real Zoom and Teams calls. Free for Windows and macOS, invisible on screen-share.
Download freeFAQ
What makes Uber's coding interview distinctive?
Two things: a strong emphasis on object-oriented design (LRU cache, rate limiter, parking lot) alongside data structures, and graph problems that mirror Uber's real domain like routing and scheduling. Clean, extensible code is rewarded over clever tricks.
Does Uber ask LeetCode-style problems?
Yes, mostly mediums, but with an above-average share of graph and design-flavored questions. Topological sort, BFS shortest path, and OOD problems show up more than at a pure-algorithms shop.
How many rounds is the Uber onsite?
Typically two coding rounds, a graph or domain round, a system design round for mid/senior candidates, and a behavioral or hiring-manager round - usually five interviews in total after the phone screen.
How hard is the Uber system design round?
Real-world and Uber-scale: design a dispatch service, surge pricing, or trip storage. Cover requirements, data model, scaling, and trade-offs. See our system design cheat sheet for the skeleton.
Can CoPilot Interview help during an Uber interview?
It's built for preparation and real-time support: it returns optimal solutions with Big-O and OOD structure in about four seconds. Use it to rehearse, and always follow Uber's stated interview rules.