Shortest Path to Get All Keys - Complete Solution Guide
Shortest Path to Get All Keys is LeetCode problem 864, a Hard level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
You are given an m x n grid grid where: '.' is an empty cell. '#' is a wall. '@' is the starting point. Lowercase letters represent keys. Uppercase letters represent locks. You start at the starting point and one move consists of walking one space in one of the four cardinal directions. You cannot walk outside the grid, or walk into a wall. If you walk over a key, you can pick it up and you cannot walk over a lock unless you have its corresponding key. For some 1 <= k <= 6 , there is exactly one
Detailed Explanation
The problem requires finding the shortest path to collect all keys in a grid. The grid contains empty cells ('.'), walls ('#'), a starting point ('@'), keys (lowercase letters), and locks (uppercase letters). You can move in four cardinal directions, pick up keys upon encountering them, and open locks only if you possess the corresponding key. The goal is to determine the minimum number of moves needed to acquire all keys. If acquiring all keys is impossible, return -1.
Solution Approach
The provided solutions use Breadth-First Search (BFS) to explore the grid. Each state in the BFS queue is represented by the current row, column, and a bitmask indicating which keys have been collected. The algorithm explores possible moves from each state, updating the keymask when a new key is found. It checks if a move is valid (not a wall, not outside the grid, and has the required key for a lock). A set `visited` is used to avoid revisiting states, where a state is defined by row, col and the key bitmask. The algorithm continues until all keys are collected or the queue is empty (indicating no path exists).
Step-by-Step Algorithm
- Step 1: Initialize variables: grid dimensions, starting position, total number of keys, and the target keymask (all keys collected).
- Step 2: Create a queue for BFS, initialize the starting state (starting row, starting column, empty keymask), and a set to track visited states.
- Step 3: Perform BFS: While the queue is not empty, process nodes level by level (to guarantee shortest path).
- Step 4: For each node in the current level, check if the current keymask equals the target keymask. If so, return the current step count.
- Step 5: Explore possible moves (up, down, left, right).
- Step 6: For each move, check if it is valid (within grid bounds and not a wall). Also check if we have the necessary key to open a lock if we encounter one. If a lock exists but the corresponding key isn't in the current mask, the move is invalid.
- Step 7: If the move is valid, update the keymask if a key is encountered. Then, add the new state to the queue and the visited set, only if the new state was never previously visited.
- Step 8: Increment the step count after processing each level of the queue.
- Step 9: If the queue becomes empty before finding all keys, return -1 (no path exists).
Key Insights
- Insight 1: The state of the search needs to include the current position (row, col) and the set of keys collected so far, represented as a bitmask.
- Insight 2: Breadth-First Search (BFS) is suitable for finding the shortest path in an unweighted graph (where each move has a cost of 1).
- Insight 3: The maximum number of keys is limited to 6, making it feasible to represent the key set as a bitmask (2^6 = 64 possible key combinations).
Complexity Analysis
Time Complexity: O(m*n*2^k)
Space Complexity: O(m*n*2^k)
Topics
This problem involves: Array, Bit Manipulation, Breadth-First Search, Matrix.
Companies
Asked at: Airbnb, Pinterest, Roku.