Quick Overview

A grid coding problem: commute from a start block to a destination using one transport mode, where each mode may enter only its own blocks and has a per-block time and cost. Return the fastest mode, breaking ties by total cost and then list order, or an empty string when no mode can reach the destination.

Fastest Single-Mode Commute Across a Grid of Mode-Restricted Blocks

Company: Databricks

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: hard

Interview Round: Onsite

A city map is a grid of blocks. You must commute from your start block to your destination block using exactly one transport mode for the whole trip, and each mode may travel only on the blocks that allow it. Every mode has a fixed travel time and a fixed cost for each move between blocks. Return the name of the mode that gets you to the destination in the least total time. The report names this problem without giving its input format; the format and tie rules below are fixed here so that every input has exactly one correct answer. ### Function Signature ```python def fastest_commute_mode(grid: list[str], modes: list[str], time_per_block: list[int], cost_per_block: list[int]) -> str: ``` ### Rules - `grid[r][c]` is one of: - `'S'`: the start block; - `'D'`: the destination block; - `'X'`: a blocked block that no mode can enter; - a digit `'1'` to `'9'`: a block that only mode number `d` can enter, where mode number `d` is `modes[d - 1]`. - A move goes from a block to one of its up to four neighbours (up, down, left, right) inside the grid. Diagonal moves are not allowed. - With mode `i` (0-based), the trip starts on `'S'`, and each move may enter only a block marked with the digit `i + 1` or the `'D'` block. If `'S'` is next to `'D'`, every mode can make the trip in one move. - A trip with mode `i` that makes `m` moves takes `m * time_per_block[i]` time and costs `m * cost_per_block[i]`. - Each mode is judged by its trip with the fewest moves. A mode that cannot reach `'D'` at all is not a candidate. - Return the name of the candidate with the smallest total time. Break ties by smaller total cost, then by smaller index in `modes`. Return the empty string `""` if no mode can reach `'D'`. ### Constraints - `1 <= len(grid) <= 200` and `1 <= len(grid[r]) <= 200`; all rows have the same length. - `grid` contains exactly one `'S'` and exactly one `'D'`; every other character is `'X'` or a digit from `'1'` to `str(len(modes))`. - `1 <= len(modes) <= 9` and `len(time_per_block) == len(cost_per_block) == len(modes)`. - Mode names are distinct, nonempty strings of English letters. - `1 <= time_per_block[i] <= 10^4` and `0 <= cost_per_block[i] <= 10^4`. - A shortest trip makes fewer than `40,000` moves, so every total time and total cost is below `4 * 10^8` and fits in a 32-bit signed integer. ### Examples **Example 1** ```text Input: grid = ["S11D", "2XX2", "2222"] modes = ["Walk", "Bike"] time_per_block = [10, 3] cost_per_block = [0, 2] Output: "Bike" ``` Walk reaches `D` along the top row in 3 moves: time 30, cost 0. Bike must go around the blocked blocks through the bottom row in 7 moves: time 21, cost 14. Bike is faster. **Example 2** ```text Input: grid = ["S22", "1X2", "11D"] modes = ["Bus", "Taxi", "Train"] time_per_block = [5, 5, 1] cost_per_block = [2, 7, 1] Output: "Bus" ``` Bus (down the left column, then along the bottom row) and Taxi (along the top row, then down the right column) both need 4 moves and take time 20. Bus costs 8 and Taxi 28, so Bus wins the tie. Train has no blocks of its own, cannot leave `S`, and is not a candidate even though it is the fastest per block. **Example 3** ```text Input: grid = ["SX", "XD"] modes = ["Walk"] time_per_block = [1] cost_per_block = [0] Output: "" ``` Every neighbour of `S` is blocked, so no mode can reach `D`.

Overview: A grid coding problem: commute from a start block to a destination using one transport mode, where each mode may enter only its own blocks and has a per-block time and cost. Return the fastest mode, breaking ties by total cost and then list order, or an empty string when no mode can reach the destination.

Read the full Databricks Software Engineer interview experience this question came from

A city map is a grid of blocks. You must commute from your start block to your destination block using exactly one transport mode for the whole trip, and each mode may travel only on the blocks that allow it. Every mode has a fixed travel time and a fixed cost for each move between blocks. Return the name of the mode that gets you to the destination in the least total time. Implement `fastest_commute_mode(grid, modes, time_per_block, cost_per_block)`. ### Rules - `grid[r][c]` is one of: - `'S'`: the start block; - `'D'`: the destination block; - `'X'`: a blocked block that no mode can enter; - a digit `'1'` to `'9'`: a block that only mode number `d` can enter, where mode number `d` is `modes[d - 1]`. - A move goes from a block to one of its up to four neighbours (up, down, left, right) inside the grid. Diagonal moves are not allowed. - With mode `i` (0-based), the trip starts on `'S'`, and each move may enter only a block marked with the digit `i + 1` or the `'D'` block. If `'S'` is next to `'D'`, every mode can make the trip in one move. - A trip with mode `i` that makes `m` moves takes `m * time_per_block[i]` time and costs `m * cost_per_block[i]`. - Each mode is judged by its trip with the fewest moves. A mode that cannot reach `'D'` at all is not a candidate. - Return the name of the candidate with the smallest total time. Break ties by smaller total cost, then by smaller index in `modes`. Return the empty string `""` if no mode can reach `'D'`. ### Example 1 ```text Input: grid = ["S11D", "2XX2", "2222"] modes = ["Walk", "Bike"] time_per_block = [10, 3] cost_per_block = [0, 2] Output: "Bike" ``` Walk reaches `D` along the top row in 3 moves: time 30, cost 0. Bike must go around the blocked blocks through the bottom row in 7 moves: time 21, cost 14. Bike is faster. ### Example 2 ```text Input: grid = ["S22", "1X2", "11D"] modes = ["Bus", "Taxi", "Train"] time_per_block = [5, 5, 1] cost_per_block = [2, 7, 1] Output: "Bus" ``` Bus (down the left column, then along the bottom row) and Taxi (along the top row, then down the right column) both need 4 moves and take time 20. Bus costs 8 and Taxi 28, so Bus wins the tie. Train has no blocks of its own, cannot leave `S`, and is not a candidate even though it is the fastest per block. ### Constraints - `1 <= len(grid) <= 200` and `1 <= len(grid[r]) <= 200`; all rows have the same length. - `grid` contains exactly one `'S'` and exactly one `'D'`; every other character is `'X'` or a digit from `'1'` to `str(len(modes))`. - `1 <= len(modes) <= 9` and `len(time_per_block) == len(cost_per_block) == len(modes)`. - Mode names are distinct, nonempty strings of English letters, each at most 20 letters long. - `1 <= time_per_block[i] <= 10^4` and `0 <= cost_per_block[i] <= 10^4`. - A shortest trip makes fewer than `40,000` moves, so every total time and total cost is below `4 * 10^8` and fits in a 32-bit signed integer; no value exceeds `2^31 - 1`.

Constraints

  • 1 <= len(grid) <= 200 and 1 <= len(grid[r]) <= 200; all rows have the same length.
  • grid contains exactly one 'S' and exactly one 'D'; every other character is 'X' or a digit from '1' to str(len(modes)).
  • 1 <= len(modes) <= 9 and len(time_per_block) == len(cost_per_block) == len(modes).
  • Mode names are distinct, nonempty strings of English letters, each at most 20 letters long.
  • 1 <= time_per_block[i] <= 10^4 and 0 <= cost_per_block[i] <= 10^4.
  • A shortest trip makes fewer than 40,000 moves, so every total time and total cost is below 4 * 10^8 and fits in a 32-bit signed integer; no value exceeds 2^31 - 1.

Examples

Input: (['S11D', '2XX2', '2222'], ['Walk', 'Bike'], [10, 3], [0, 2])

Expected Output: 'Bike'

Explanation: Source example 1: Walk needs 3 moves (time 30, cost 0), Bike detours in 7 moves (time 21, cost 14); total time decides, so Bike wins.

Input: (['S22', '1X2', '11D'], ['Bus', 'Taxi', 'Train'], [5, 5, 1], [2, 7, 1])

Expected Output: 'Bus'

Explanation: Source example 2: Bus and Taxi both need 4 moves and time 20; Bus costs 8 against 28. Train has no blocks, cannot leave S and is not a candidate though fastest per block.

Hints

  1. The modes never interact: settle one mode at a time, treating every block that mode cannot enter, other than 'D', exactly like 'X'.
  2. Only the number of moves in a mode's shortest trip matters; its total time and total cost are that count times the mode's per-block values.
  3. Compare candidates on total time, then total cost, then index, and skip any mode that never reaches 'D'.

Loading coding console...

Show the approach

Approach

Handle each mode i on its own. Run a breadth-first search from 'S' in which the only enterable blocks are those marked with the digit i + 1 and the 'D' block; 'X' and every other mode's digit act as walls, and 'S' is the origin at distance 0 that is never entered again, so it never counts as a block of any mode. BFS dequeues blocks in nondecreasing order of moves, so the first time 'D' appears as a neighbour of a dequeued block at distance d, d + 1 is that mode's fewest-move trip; if the queue empties first, the mode is not a candidate. A candidate with m moves has total time m * time_per_block[i] and total cost m * cost_per_block[i] (only the move count of the fewest-move trip matters, since both totals scale with it). Scan the modes in index order and replace the current best only when (total time, total cost) is strictly smaller, so a full tie keeps the smaller index. If no mode is a candidate, return the empty string. Edge cases: when 'S' is next to 'D', every mode, even one with no blocks of its own, finishes in one move; a mode with no blocks and no adjacent 'D' never leaves 'S'; a mode that is fastest per block but has no path is skipped. Totals stay below 4 * 10^8, inside 32-bit range; the Java and C++ references multiply in 64-bit anyway.

Time complexity:
O(k * R * C), where k = len(modes) <= 9 and R x C is the grid size
Space complexity:
O(R * C)