题目
题目描述: 在一个二维矩阵中,每个格子有一个值,代表一把钥匙或者一个锁。钥匙的值是一个正整数,锁的值是一个负整数。从矩阵的左上角出发,只能向右或向下移动,目标是找到一把关键钥匙,该钥匙能够打开所有遇到的锁,并且路径上遇到的钥匙值都不重复。返回该关键钥匙的值,如果不存在这样的钥匙,则返回 -1。
输入:
- 一个二维矩阵 matrix,其中每个元素是整数,代表钥匙或者锁。
输出:
- 关键钥匙的值,如果不存在则返回 -1。
示例:
输入:
[
[1, -2, 3],
[-4, 5, -6],
[7, -8, 9]
]
输出:
5
解释:
从左上角出发,可以走到 (1,1) 拿到钥匙 5,然后可以打开所有锁:-2, -4, -6, -8。
思路
- 深度优先搜索(DFS):
- 从左上角开始,进行深度优先搜索。
- 在搜索过程中,记录当前路径上遇到的所有钥匙值,用于判断是否能打开所有遇到的锁。
- 如果能到达某个格子,并且该格子的钥匙值在路径上未出现过,则更新当前能够打开的最大锁值。
- 剪枝:
- 如果当前路径上的钥匙值不能打开当前遇到的锁,则直接返回,无需继续搜索。
- 如果当前路径上的钥匙集合已经能够打开所有遇到的锁,则更新关键钥匙候选值。
- 回溯:
- 在回溯时,要恢复状态,即移除当前路径上的钥匙值。
Java 编码解析
import java.util.*;
public class KeyFinder {
private static final int[][] DIRECTIONS = {
{0, 1}, {1, 0}};
public static int findKey(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
Set<Integer> visitedKeys = new HashSet<>();
return dfs(matrix, 0, 0, visitedKeys, m, n);
}
private static int dfs(int[][] matrix, int x, int y, Set<Integer> visitedKeys, int m, int n) {
int maxUnlockValue = Integer.MIN_VALUE;
int currentValue = matrix[x][y];
if (currentValue > 0 && !visitedKeys.contains(currentValue)) {
visitedKeys.add(currentValue);
maxUnlockValue = currentValue;
for (int[] dir : DIRECTIONS) {
int newX = x + dir[0];
int newY = y + dir[1];
if (newX >= 0 && newX < m && newY >= 0 && newY < n) {
int neighborValue = matrix[newX][newY];
if (neighborValue > 0) {
// Ignore if it's a key and already visited
} else if (neighborValue > maxUnlockValue) {
// Can't unlock this lock, skip further search
continue;
} else {
int result = dfs(matrix, newX, newY, visitedKeys, m, n);
if (result != -1) {
return result;
}
}
}
}
}
// Backtrack: remove the current key from visited set
if (currentValue > 0) {
visitedKeys.remove(currentValue);
}
// If we reach here, it means no valid key was found in this path
// But if we've visited a key, return its value if it can unlock all locks in path
return visitedKeys.isEmpty() ? -1 : Collections.max(visitedKeys);
}
public static void main(String[] args) {
int[][] matrix = {
{1, -2, 3},
{-4, 5, -6},
{7, -8, 9}
};
System.out.println(findKey(matrix)); // Output: 5
}
}
C++ 编码解析
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
using namespace std;
const int dirs[2][2] = {
{0, 1}, {1, 0}};
int findKey(vector<vector<int>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();
unordered_set<int> visitedKeys;
return dfs(matrix, 0, 0, visitedKeys, m, n);
}
int dfs(vector<vector<int>>& matrix, int x, int y, unordered_set<int>& visitedKeys, int m, int n) {
int maxUnlockValue = INT_MIN;
int currentValue = matrix[x][y];
if (currentValue > 0 && visitedKeys.find(currentValue) == visitedKeys.end()) {
visitedKeys.insert(currentValue);
maxUnlockValue = currentValue;
for (const auto& dir : dirs) {
int newX = x + dir[0];
int newY = y + dir[1];
if (newX >= 0 && newX < m && newY >= 0 && newY < n) {
int neighborValue = matrix[newX][newY];
if (neighborValue > 0) {
// Ignore if it's a key and already visited
} else if (neighborValue > maxUnlockValue) {
// Can't unlock this lock, skip further search
continue;
} else {
int result = dfs(matrix, newX, newY, visitedKeys, m, n);
if (result != -1) {
return result;
}
}
}
}
}
// Backtrack: remove the current key from visited set
if (currentValue > 0) {
visitedKeys.erase(currentValue);
}
// If we reach here, it means no valid key was found in this path
// But if we've visited a key, return its value if it can unlock all locks in path
if (visitedKeys.empty()) {
return -1;
} else {
int maxKey = *max_element(visitedKeys.begin(), visitedKeys.end());
return maxKey;
}
}
int main() {
vector<vector<int>> matrix = {
{1, -2, 3},
{-4, 5, -6},
{7, -8, 9}
};
cout << findKey(matrix) << endl; // Output: 5
return 0;
}
Python 编码解析
def findKey(matrix):
def dfs(x, y, visited_keys):
max_unlock_value = float('-inf')
current_value = matrix[x][y]
if current_value > 0 and current_value not in visited_keys:
visited_keys.add(current_value)
max_unlock_value = current_value
for dx, dy in [(0, 1), (1, 0)]:
new_x, new_y = x + dx, y + dy
if 0 <= new_x < len(matrix) and 0 <= new_y < len(matrix[0]):
neighbor_value = matrix[new_x][new_y]
if neighbor_value > 0:
# Ignore if it's a key and already visited
pass
elif neighbor_value > max_unlock_value:
# Can't unlock this lock, skip further search
continue
else:
result = dfs(new_x, new_y, visited_keys)
if result != -1:
return result
# Backtrack: remove the current key from visited set
if current_value > 0:
visited_keys.remove(current_value)
# If we reach here, it means no valid key was found in this path
# But if we've visited a key, return its value if it can unlock all locks in path
return max(visited_keys) if visited_keys else -1
m, n = len(matrix), len(matrix[0])
return dfs(0, 0, set())