
华为OD机试 2024E卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
从一个 N×M(N≤M)的矩阵中选出 N 个数,任意两个数字不能在同一行或同一列,求选出来的 N 个数中第 K 大的数字的最小值是多少。
二、输入描述
输入矩阵要求: 1≤K≤N≤M≤150
输入格式:
N M K
N*M矩阵
 
三、输出描述
N×M 的矩阵中可以选出 M!/N!种组合数组,每个组合数组种第 K 大的数中的最小值。无需考虑重复数字,直接取字典排序结果即可。
备注:
注意:结果是第 K 大的数字的最小值
四、测试用例
测试用例1:
1、输入
3 3 2
 2 1 4
 5 3 7
 9 6 8
2、输出
3
测试用例2:
1、输入
3 4 2
 1 5 6 6
 8 3 4 3
 6 8 6 3
2、输出
3
3、说明
第一行:[2, 3, 4],第2大的数是3
 第二行:[1, 5, 6, 6],第2大的数是6
 第三行:[3, 3, 4, 8],第2大的数是4
 第四行:[3, 6, 6, 8],第2大的数是6
所有行的第2大数中的最小值是3。
输出:3
五、解题思路
1、深度优先搜索DFS
深度优先搜索(Depth-First Search, DFS)是一种用于遍历或搜索图或树结构的算法。DFS算法从一个起始节点开始,沿着某一路径尽可能深入到一个分支的底部,然后回溯并继续探索其他分支,直到所有节点都被访问过。
DFS的核心思想是尽可能深地搜索树或图的分支,直到遇到已访问的节点或没有未访问的邻接节点为止,然后回溯到上一个节点继续搜索。
2、为什么采用深度优先搜索DFS?
在这个问题中,我们需要从一个矩阵中选择一定数量的元素,这些元素必须满足不在同一行或同一列的限制条件,同时还要找到这些元素中第 K 大的元素的最小值。这种问题的关键在于需要系统地探索所有可能的选择组合,并检查每个组合是否满足特定的条件。
DFS算法通过递归的方式深入搜索,能够遍历所有可能的选择组合。在这个问题中,DFS可以从每个矩阵元素开始,尝试选择下一个元素时递归地检查不同行不同列的约束,直到选择到足够数量的元素为止。这种方法确保不会遗漏任何一个可能的组合。
3、具体步骤:
对于给定的矩阵和选择的数量 K,问题要求从矩阵中选择 K 个数字,这些数字不能位于同一行或同一列,然后找出所有可能组合中第 K 大的数字的最小值。解题的主要步骤如下:
- 读取输入数据: 
  
- 获取矩阵的行数 N、列数 M 和需要选择的数量 K。
 - 读取 N*M 的矩阵数据。
 
 - 选择组合: 
  
- 使用DFS进行深度优先搜索,选择矩阵中的 K 个元素。
 - 在每次选择时,确保选定的数字不在已选数字的行和列中。
 
 - 计算组合中第 K 大的数字: 
  
- 对于每个有效的选择组合,排序并找到该组合中的第 K 大数字。
 
 - 记录最小值: 
  
- 记录所有组合中第 K 大的数字,最终取这些数字中的最小值作为结果。
 
 - 输出结果: 
  
- 输出最小的第 K 大数字。
 
 
六、Python算法源码
def main():
    # 读取输入
    N = int(input())
    M = int(input())
    K = int(input())
    matrix = []
    for _ in range(N):
        matrix.append(list(map(int, input().split())))
    # 存储每个组合的第K大的最小值
    min_kth_values = []
    # 从矩阵中选择 K 个数字
    select_numbers(matrix, N, M, K, [], min_kth_values)
    # 找到所有组合中的第 K 大的最小值
    result = min(min_kth_values)
    print(result)
def select_numbers(matrix, N, M, K, current_selection, min_kth_values):
    if len(current_selection) == K:
        # 对于每个选择,找到第 K 大的值
        current_selection.sort()
        min_kth_values.append(current_selection[K - 1])
        return
    for i in range(N):
        for j in range(M):
            if can_be_selected(i, j, current_selection, matrix, N, M):
                current_selection.append(matrix[i][j])
                select_numbers(matrix, N, M, K, current_selection, min_kth_values)
                current_selection.pop()
def can_be_selected(row, col, current_selection, matrix, N, M):
    # 检查行列约束
    for num in current_selection:
        position = find_position(num, matrix, N, M)
        if position[0] == row or position[1] == col:
            return False
    return True
def find_position(num, matrix, N, M):
    for i in range(N):
        for j in range(M):
            if matrix[i][j] == num:
                return (i, j)
    return (-1, -1)  # 不会发生
if __name__ == "__main__":
    main()
 
七、JavaScript算法源码
function main() {
    const fs = require('fs');
    const input = fs.readFileSync('/dev/stdin', 'utf8').trim().split('\n');
    
    const N = parseInt(input[0]);
    const M = parseInt(input[1]);
    const K = parseInt(input[2]);
    const matrix = [];
    for (let i = 0; i < N; i++) {
        matrix.push(input[3 + i].split(' ').map(Number));
    }
    // 存储每个组合的第K大的最小值
    const minKthValues = [];
    // 从矩阵中选择 K 个数字
    selectNumbers(matrix, N, M, K, [], minKthValues);
    // 找到所有组合中的第 K 大的最小值
    const result = Math.min(...minKthValues);
    console.log(result);
}
function selectNumbers(matrix, N, M, K, currentSelection, minKthValues) {
    if (currentSelection.length === K) {
        // 对于每个选择,找到第 K 大的值
        currentSelection.sort((a, b) => a - b);
        minKthValues.push(currentSelection[K - 1]);
        return;
    }
    for (let i = 0; i < N; i++) {
        for (let j = 0; j < M; j++) {
            if (canBeSelected(i, j, currentSelection, matrix, N, M)) {
                currentSelection.push(matrix[i][j]);
                selectNumbers(matrix, N, M, K, currentSelection, minKthValues);
                currentSelection.pop();
            }
        }
    }
}
function canBeSelected(row, col, currentSelection, matrix, N, M) {
    // 检查行列约束
    for (let num of currentSelection) {
        const position = findPosition(num, matrix, N, M);
        if (position[0] === row || position[1] === col) {
            return false;
        }
    }
    return true;
}
function findPosition(num, matrix, N, M) {
    for (let i = 0; i < N; i++) {
        for (let j = 0; j < M; j++) {
            if (matrix[i][j] === num) {
                return [i, j];
            }
        }
    }
    return [-1, -1]; // 不会发生
}
// 如果在Node.js环境中运行,调用main函数
main();
 
八、C算法源码
#include <stdio.h>
#include <stdlib.h>
#define MAX_N 100
void selectNumbers(int matrix[MAX_N][MAX_N], int N, int M, int K, int* currentSelection, int currentSize, int* minKthValues, int* minKthValuesSize);
int canBeSelected(int row, int col, int* currentSelection, int currentSize, int matrix[MAX_N][MAX_N], int N, int M);
void findPosition(int num, int matrix[MAX_N][MAX_N], int N, int M, int* row, int* col);
int main() {
    int N, M, K;
    int matrix[MAX_N][MAX_N];
    scanf("%d %d %d", &N, &M, &K);
    // 读取矩阵
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            scanf("%d", &matrix[i][j]);
        }
    }
    // 存储每个组合的第K大的最小值
    int minKthValues[MAX_N * MAX_N];
    int minKthValuesSize = 0;
    int currentSelection[MAX_N];
    // 从矩阵中选择 K 个数字
    selectNumbers(matrix, N, M, K, currentSelection, 0, minKthValues, &minKthValuesSize);
    // 找到所有组合中的第 K 大的最小值
    int result = minKthValues[0];
    for (int i = 1; i < minKthValuesSize; i++) {
        if (minKthValues[i] < result) {
            result = minKthValues[i];
        }
    }
    printf("%d\n", result);
    return 0;
}
void selectNumbers(int matrix[MAX_N][MAX_N], int N, int M, int K, int* currentSelection, int currentSize, int* minKthValues, int* minKthValuesSize) {
    if (currentSize == K) {
        // 对于每个选择,找到第 K 大的值
        int sortedSelection[MAX_N];
        for (int i = 0; i < K; i++) {
            sortedSelection[i] = currentSelection[i];
        }
        // 排序选择的元素
        for (int i = 0; i < K - 1; i++) {
            for (int j = 0; j < K - i - 1; j++) {
                if (sortedSelection[j] > sortedSelection[j + 1]) {
                    int temp = sortedSelection[j];
                    sortedSelection[j] = sortedSelection[j + 1];
                    sortedSelection[j + 1] = temp;
                }
            }
        }
        minKthValues[(*minKthValuesSize)++] = sortedSelection[K - 1];
        return;
    }
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (canBeSelected(i, j, currentSelection, currentSize, matrix, N, M)) {
                currentSelection[currentSize] = matrix[i][j];
                selectNumbers(matrix, N, M, K, currentSelection, currentSize + 1, minKthValues, minKthValuesSize);
            }
        }
    }
}
int canBeSelected(int row, int col, int* currentSelection, int currentSize, int matrix[MAX_N][MAX_N], int N, int M) {
    // 检查行列约束
    for (int i = 0; i < currentSize; i++) {
        int r, c;
        findPosition(currentSelection[i], matrix, N, M, &r, &c);
        if (r == row || c == col) {
            return 0;
        }
    }
    return 1;
}
void findPosition(int num, int matrix[MAX_N][MAX_N], int N, int M, int* row, int* col) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (matrix[i][j] == num) {
                *row = i;
                *col = j;
                return;
            }
        }
    }
    *row = -1;
    *col = -1;  // 不会发生
}
 
九、C++算法源码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define MAX_N 100
void selectNumbers(int matrix[MAX_N][MAX_N], int N, int M, int K, vector<int>& currentSelection, vector<int>& minKthValues);
bool canBeSelected(int row, int col, const vector<int>& currentSelection, int matrix[MAX_N][MAX_N], int N, int M);
pair<int, int> findPosition(int num, int matrix[MAX_N][MAX_N], int N, int M);
int main() {
    int N, M, K;
    int matrix[MAX_N][MAX_N];
    cin >> N >> M >> K;
    // 读取矩阵
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            cin >> matrix[i][j];
        }
    }
    // 存储每个组合的第K大的最小值
    vector<int> minKthValues;
    vector<int> currentSelection;
    // 从矩阵中选择 K 个数字
    selectNumbers(matrix, N, M, K, currentSelection, minKthValues);
    // 找到所有组合中的第 K 大的最小值
    int result = *min_element(minKthValues.begin(), minKthValues.end());
    cout << result << endl;
    return 0;
}
void selectNumbers(int matrix[MAX_N][MAX_N], int N, int M, int K, vector<int>& currentSelection, vector<int>& minKthValues) {
    if (currentSelection.size() == K) {
        // 对于每个选择,找到第 K 大的值
        vector<int> sortedSelection = currentSelection;
        sort(sortedSelection.begin(), sortedSelection.end());
        minKthValues.push_back(sortedSelection[K - 1]);
        return;
    }
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (canBeSelected(i, j, currentSelection, matrix, N, M)) {
                currentSelection.push_back(matrix[i][j]);
                selectNumbers(matrix, N, M, K, currentSelection, minKthValues);
                currentSelection.pop_back();
            }
        }
    }
}
bool canBeSelected(int row, int col, const vector<int>& currentSelection, int matrix[MAX_N][MAX_N], int N, int M) {
    // 检查行列约束
    for (int num : currentSelection) {
        pair<int, int> position = findPosition(num, matrix, N, M);
        if (position.first == row || position.second == col) {
            return false;
        }
    }
    return true;
}
pair<int, int> findPosition(int num, int matrix[MAX_N][MAX_N], int N, int M) {
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++) {
            if (matrix[i][j] == num) {
                return make_pair(i, j);
            }
        }
    }
    return make_pair(-1, -1); // 不会发生
}
 
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。


















