【2024华为OD-E卷-100分-寻找关键钥匙】(题目+思路+Java&C++&Python解析)

题目

题目描述: 在一个二维矩阵中,每个格子有一个值,代表一把钥匙或者一个锁。钥匙的值是一个正整数,锁的值是一个负整数。从矩阵的左上角出发,只能向右或向下移动,目标是找到一把关键钥匙,该钥匙能够打开所有遇到的锁,并且路径上遇到的钥匙值都不重复。返回该关键钥匙的值,如果不存在这样的钥匙,则返回 -1。

输入

  • 一个二维矩阵 matrix,其中每个元素是整数,代表钥匙或者锁。

输出

  • 关键钥匙的值,如果不存在则返回 -1。

示例

输入:
[
  [1, -2, 3],
  [-4, 5, -6],
  [7, -8, 9]
]
输出:
5
解释:
从左上角出发,可以走到 (1,1) 拿到钥匙 5,然后可以打开所有锁:-2, -4, -6, -8。

思路

  1. 深度优先搜索(DFS)
    • 从左上角开始,进行深度优先搜索。
    • 在搜索过程中,记录当前路径上遇到的所有钥匙值,用于判断是否能打开所有遇到的锁。
    • 如果能到达某个格子,并且该格子的钥匙值在路径上未出现过,则更新当前能够打开的最大锁值。
  2. 剪枝
    • 如果当前路径上的钥匙值不能打开当前遇到的锁,则直接返回,无需继续搜索。
    • 如果当前路径上的钥匙集合已经能够打开所有遇到的锁,则更新关键钥匙候选值。
  3. 回溯
    • 在回溯时,要恢复状态,即移除当前路径上的钥匙值。

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())
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

执着的小火车

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值