↓Skip to main content
  1. LeetCode/

LeetCode 864: Shortest Path to Get All Keys

·3 mins· ·
LeetCode Hard Bfs Bit-Manipulation Matrix
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: hard First Attempt: 2026-09-05

  • Submissions: Accepted → Accepted (cleaned up)

Approach
#

Walk a grid where a lock can be passed only after picking up its key; find the fewest steps to collect every key.

Position alone is not enough: standing on the same cell with different keys allows different moves. So the BFS state is (r, c, keys), with keys as a bitmask (at most 6 keys, 2^6 = 64 combinations).

  • Stepping on a key: add it to the mask.
  • Stepping on a lock: allowed only if the mask holds its key.
  • When the mask equals “all keys”, the current step count is the answer.

My Solution
#

from collections import deque

class Solution:
    def shortestPathAllKeys(self, grid: List[str]) -> int:
        m, n = len(grid), len(grid[0])
        total = 0
        for r in range(m):
            for c in range(n):
                if grid[r][c] == "@":
                    start = (r, c)
                elif grid[r][c].islower():
                    total += 1
        full = (1 << total) - 1

        q = deque([(start[0], start[1], 0, 0)])            # r, c, keys, steps
        seen = {(start[0], start[1], 0)}
        while q:
            r, c, keys, steps = q.popleft()
            if keys == full:
                return steps
            for nr, nc in ((r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)):
                if not (0 <= nr < m and 0 <= nc < n) or grid[nr][nc] == "#":
                    continue
                ch = grid[nr][nc]
                if ch.isupper() and not keys >> (ord(ch) - ord("A")) & 1:
                    continue                               # no key, cannot pass
                nkeys = keys | (1 << (ord(ch) - ord("a"))) if ch.islower() else keys
                if (nr, nc, nkeys) not in seen:
                    seen.add((nr, nc, nkeys))
                    q.append((nr, nc, nkeys, steps + 1))
        return -1

Complexity
#

Time O(mn · 2^k), where k is the number of keys. Space O(mn · 2^k).

Mistakes to Avoid
#

  • visited storing only the position: paths that double back after picking up a key get blocked.
  • Hard-coding 6 keys: build the “all keys” mask from the keys actually in the grid.
  • Marking visited cells in place on the grid: with different keys you may need to pass the same cell again, so the mark belongs in a seen set that includes the key mask.

Interview Explanation
#

Holding different keys on the same cell changes where you can go next, so the BFS state is the position plus a bitmask of keys. Stepping on a key sets its bit, and a lock requires its bit to be set. visited stores the whole state, and the first time the mask is full, the step count is the answer. There are mn · 2^k states, with k at most 6.

Related

LeetCode 2328: Number of Increasing Paths in a Grid
·2 mins
LeetCode Hard Dynamic-Programming Grid-Dp Memoization Topological-Sort Matrix
LeetCode 2328 note: strictly increasing means no cycles; dp[cell] = 1 + Σ dp[larger neighbors], processed from largest to smallest value (or by memoized DFS), summed over all cells
LeetCode 1178: Number of Valid Words for Each Puzzle
·3 mins
LeetCode Hard Bit-Manipulation Hash-Map Trie
LeetCode 1178 note: a word only matters by its set of letters, so count 26-bit masks and enumerate each puzzle’s submasks
LeetCode 2392: Build a Matrix With Conditions
·2 mins
LeetCode Hard Graph Topological-Sort Matrix
LeetCode 2392 note: row and column conditions are independent, so run one topological sort for each; put x at its row and column positions, and return an empty matrix if either has a cycle
LeetCode 3548: Equal Sum Grid Partition II
·3 mins
LeetCode Hard Prefix-Sum Hash-Table Matrix Enumeration
LeetCode 3548 note: try each horizontal cut (transpose for vertical); the difference must equal a cell on the larger side, and a one-row or one-column side can only drop an end cell, while any cell works otherwise
LeetCode 980: Unique Paths III
·2 mins
LeetCode Hard Backtracking Matrix Dfs
LeetCode 980 note: grid backtracking that marks visited cells in place and checks at the end that every empty cell was covered
LeetCode 3989: Maximum Consistent Columns in a Grid
·2 mins
LeetCode Hard Dynamic-Programming Matrix Array
LeetCode 3989 note: the kept columns form a subsequence constrained only between neighbors; an LIS-style DP with dp[j] = the longest valid sequence ending at column j