← DoorDash Interview Insights

DoorDash·Software Engineer·Technical Phone Screen·Intermediate

Intermediate
Jun 2026

Summary

DoorDash coding round, pretty much one meaty grid problem that kept expanding with follow-ups. The core question was straightforward but the extensions kept coming and I wasn't fully prepared for all of them.

Questions Asked (4)

Q1

Given a 2D grid with warehouses, customers, obstacles, and roads, find the minimum number of steps from any warehouse to each customer cell. Return -1 for unreachable customers. Define your input/output format and justify your data structure choices.

Algorithms & Data StructuresSystem Design
Author's notes

Multi-source BFS was the right move here, seed all warehouse cells at once and let it fan out.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Clarify the grid representation and define input/output formats, then propose a multi-source BFS from all warehouses simultaneously to compute shortest distances to all cells. Justify using a queue for BFS and a distance matrix for O(1) lookups, and discuss handling obstacles and unreachable customers.

Pro tip: Mention that multi-source BFS is optimal for unweighted grids and that you can early-terminate once all customers are reached, which is crucial for DoorDash's large-scale delivery scenarios.

1. Clarify Input/Output and Assumptions

Define the grid format (e.g., 2D array of characters: 'W' for warehouse, 'C' for customer, 'O' for obstacle, '.' for road) and output as a 2D array of integers with distances or -1. Confirm movement allowed in 4 directions and that each step costs 1.

2. Choose Data Structures and Justify

Use a queue for BFS to process cells in order of distance, and a 2D distance array initialized to -1 to store results and track visited cells. Justify: BFS guarantees shortest path in unweighted graphs, and the distance array provides O(1) access and avoids revisiting.

3. Initialize Multi-Source BFS

Enqueue all warehouse cells with distance 0, marking them visited. This treats all warehouses as sources, ensuring each cell gets the minimum distance from any warehouse.

4. Perform BFS and Record Distances

While queue is not empty, dequeue a cell, explore its 4 neighbors. If a neighbor is within bounds, not an obstacle, and unvisited, set its distance to current distance + 1, enqueue it, and if it's a customer, record the distance.

5. Return Results and Discuss Optimizations

After BFS, return the distance array (or only customer distances). Discuss early termination when all customers are reached, and analyze time/space complexity: O(R*C) time and space.

Key Points to Mention

  • Multi-source BFS efficiently computes shortest paths from multiple sources in one pass.
  • BFS is optimal for unweighted grids; Dijkstra would be overkill.
  • Use a 2D distance array to store results and avoid revisiting cells.
  • Obstacles are treated as blocked cells and are not enqueued.
  • Unreachable customers remain -1 in the distance array.
  • Time and space complexity are O(R*C) for an R x C grid.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

How would you scale this solution to handle a grid with millions of cells, considering both memory and time constraints?

System DesignTechnical Trade-offs
Author's notes

I talked about not materializing the full output grid if most cells are roads, maybe a sparse map for results.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the problem constraints and the current solution's bottlenecks, then propose a scalable architecture that addresses memory and time separately. Discuss trade-offs between different strategies (e.g., partitioning, streaming, approximation) and justify your choices based on the specific requirements.

Pro tip: Quantify the scale: estimate memory and time for millions of cells to show you understand the magnitude, and mention that you'd validate with back-of-the-envelope calculations before committing to a design.

1. Clarify Requirements and Constraints

Ask about the grid's characteristics (sparse vs. dense, access patterns, update frequency) and the acceptable latency/throughput. This determines whether you need exact or approximate results.

2. Identify Bottlenecks in Current Solution

Analyze where the current solution fails: memory (storing entire grid), time (O(n^2) operations), or both. This focuses your scaling efforts.

3. Propose Memory Optimization Strategies

Suggest techniques like sparse representations, compression, partitioning (sharding), or using disk-based storage with caching. Discuss trade-offs (e.g., speed vs. memory).

4. Propose Time Optimization Strategies

Consider parallelization (e.g., MapReduce, GPU), incremental computation, indexing, or approximation algorithms. Explain how these reduce time complexity.

5. Discuss Trade-offs and Validate

Compare alternatives (e.g., exact vs. approximate, in-memory vs. distributed) and recommend a solution based on constraints. Mention how you'd test and monitor performance.

Key Points to Mention

  • Partitioning/sharding the grid to distribute memory and computation across nodes
  • Using sparse data structures if the grid is sparse (e.g., hash maps, quadtrees)
  • Parallel processing frameworks (e.g., MapReduce, Spark) for time efficiency
  • Caching frequently accessed cells or precomputed results
  • Approximation algorithms or sampling when exact results are not required
  • Trade-offs between memory and time (e.g., precomputation vs. on-the-fly)

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

If road cells have non-uniform movement costs instead of uniform cost-1, how would you adapt your solution?

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

Straightforward pivot to Dijkstra with a min-heap.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, clarify that the problem shifts from BFS to a weighted shortest-path problem, so Dijkstra's algorithm (or A* with an admissible heuristic) is the natural adaptation. Then, explain how to modify the graph representation and algorithm to handle non-uniform costs, and discuss trade-offs like time complexity and potential optimizations.

Pro tip: Mention that if costs are small positive integers, you can use Dial's algorithm (bucket queue) for O(V+E) time, showing you know when to avoid a full heap-based Dijkstra. Also, emphasize that you'd confirm whether costs are static or dynamic, as that affects algorithm choice.

1. Identify the problem type

Recognize that non-uniform movement costs turn the grid into a weighted graph, so BFS no longer guarantees shortest paths. State that you need a shortest-path algorithm for weighted graphs.

2. Choose the right algorithm

Select Dijkstra's algorithm for non-negative weights, or A* with a consistent heuristic for better performance. Mention alternatives like Bellman-Ford if negative weights are possible (though unlikely for road costs).

3. Adapt the graph representation

Explain how to model the grid as a graph where each cell is a node and edges have weights equal to the cost of moving into the neighboring cell. Discuss whether to use an implicit graph (compute neighbors on the fly) or explicit adjacency list.

4. Analyze complexity and trade-offs

Compare time and space complexity: Dijkstra with binary heap is O((V+E) log V), while A* can be faster with a good heuristic. Discuss potential optimizations like bidirectional search or Dial's algorithm for small integer weights.

5. Consider edge cases and constraints

Address assumptions: are costs static? Are they positive? What about large grids? Mention that if costs are dynamic, you might need to recompute or use incremental algorithms.

Key Points to Mention

  • BFS vs Dijkstra: BFS works for unweighted graphs, but non-uniform costs require Dijkstra or A*.
  • Dijkstra's algorithm: uses a priority queue to always expand the lowest-cost node; works for non-negative weights.
  • A* search: uses a heuristic (e.g., Manhattan distance) to guide search; requires admissible and consistent heuristic for optimality.
  • Time complexity: Dijkstra with binary heap is O((V+E) log V); with Fibonacci heap O(E + V log V); A* depends on heuristic.
  • Optimizations: Dial's algorithm (bucket queue) for small integer weights; bidirectional search; early termination when target is reached.
  • Edge cases: negative weights (use Bellman-Ford), dynamic costs (recompute or use incremental algorithms), large grids (memory considerations).

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

For a subset of customer cells, how would you return the actual paths taken, not just the minimum distances?

Algorithms & Data Structures
Author's notes

Blanked for a second.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Explain that to return actual paths, you need to modify the shortest path algorithm to track predecessors for each node, then reconstruct paths by backtracking from the destination. For multiple customer cells, run the algorithm from the source to all destinations or vice versa, storing parent pointers for each node. Finally, reconstruct each path individually using the stored predecessors.

Pro tip: Mention that for large graphs, storing full paths for all nodes can be memory-intensive, so consider storing only parent pointers and reconstructing paths on demand. Also, discuss how to handle multiple sources or destinations efficiently, such as running a single-source shortest path from the depot and reconstructing paths to each customer.

1. Choose the right shortest path algorithm

Select an algorithm like Dijkstra or BFS (for unweighted graphs) that can compute shortest distances from a source to all nodes. Ensure it can be augmented to track predecessors.

2. Augment algorithm to track predecessors

During relaxation, whenever you update the shortest distance to a node, also record the predecessor node that provided the better path. This builds a predecessor tree.

3. Run algorithm for the relevant source(s)

If there are multiple customer cells, decide whether to run from the depot to all customers or from each customer to the depot, based on graph size and directionality. Typically, one run from the depot suffices if paths are needed from depot to customers.

4. Reconstruct paths for each customer

For each customer cell, backtrack from the customer to the source using the predecessor pointers, then reverse the sequence to get the path from source to customer.

5. Optimize for memory and performance

If memory is a concern, avoid storing full paths for all nodes; instead, store only predecessors and reconstruct paths on demand. Consider early termination if only a subset of destinations is needed.

Key Points to Mention

  • Dijkstra's algorithm or BFS for shortest paths
  • Predecessor tracking (parent pointers) during relaxation
  • Path reconstruction by backtracking from destination
  • Handling multiple destinations efficiently (single-source to all)
  • Memory optimization: storing predecessors vs. full paths
  • Time complexity: O(E log V) for Dijkstra with binary heap, plus O(path length) per reconstruction

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.