华为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在线答疑。