首页 > 编程语言 >矩阵匹配【华为OD机试JAVA&Python&C++&JS题解】

矩阵匹配【华为OD机试JAVA&Python&C++&JS题解】

时间:2024-03-31 11:59:41浏览次数:30  
标签:元素 matrix Python 题解 OD int ans 排序

一. 题目-矩阵匹配

从一个NM(N<=M)的矩阵中选出N个数,任意两个数字不能在同一行或同一列,求选出来的N个数中第K大的数字的最小值是多少。
输入描述:
输入矩阵要求:1<=K<=N<=M<=150
输入格式:N M K
N
M矩阵
输出描述:
N*M的矩阵中可以选出M!/N!种组合数组,每个组合数组中第K大的数中的最小值。无需考虑重复数字,直接取字典排序结果即可。

补充说明:注意:结果是第K大的数字的最小值

示例1

输入:3 4 2

     1 5 6 6 

     8 3 4 3

     6 8 6 3

输出:3

说明:N*M的矩阵中可以选出M!/N!种组合数组,每个组合数组中第K大的数中的最小值;上述输入中选出的数组组合为1,3,6; 1,3,3; 1,4,8; 1,4,3;…上述输入样例中选出的组合数组有24种,最小数组为1,3,3,则2大的最小值为3

二.解题思路

  1. 生成所有包含N个数字的组合:

    • 使用itertools.combinations或其他方法从给定的矩阵中生成所有包含N个数字的可能组合。
  2. 计算每个组合中第K大的元素:

    • 对于每个生成的组合,按降序对数字进行排序并选择第K个元素。这就是该组合中第K大的元素。
  3. 收集所有第K大的元素:

    • 将从每个组合中获得的第K大的元素存储在一个列表中。
  4. 对第K大的元素列表进行排序:

    • 对第K大的元素列表按升序进行排序。
  5. 输出排序后的列表中的最小元素:

    • 输出排序后的列表中的第一个元素,即为第K大的数字的最小值。

三.题解代码

Python题解代码

from itertools import combinations
 
def find_min_kth_largest(matrix, k):
    n = len(matrix)
    m = len(matrix[0])
    all_combinations = list(combinations(range(m), n))
    min_kth_largest = float('inf')
    for comb in all_combinations:
        selected_numbers = [matrix[i][j] for i, j in enumerate(comb)]
        selected_numbers.sort(reverse=True)
        min_kth_largest = min(min_kth_largest, selected_numbers[k-1])
    return min_kth_largest

JAVA题解代码

import java.util.*;
 
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int M = sc.nextInt();
        int K = sc.nextInt();
        int[][] matrix = new int[M][N];
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                matrix[i][j] = sc.nextInt();
            }
        }
        List<Integer> result = new ArrayList<>();
        findCombinations(matrix, new boolean[M], 0, N, new ArrayList<>(), result);
        Collections.sort(result);
        System.out.println(result.get(K - 1));
    }
 
    private static void findCombinations(int[][] matrix, boolean[] visited, int start, int count, List<Integer> current, List<Integer> result) {
        if (count == 0) {
            List<Integer> temp = new ArrayList<>(current);
            Collections.sort(temp);
            result.add(temp.get(temp.size() - K));
            return;
        }
        for (int i = start; i < matrix.length; i++) {
            if (!visited[i]) {
                visited[i] = true;
                for (int j = 0; j < matrix[i].length; j++) {
                    current.add(matrix[i][j]);
                    findCombinations(matrix, visited, i + 1, count - 1, current, result);
                    current.remove(current.size() - 1);
                }
                visited[i] = false;
            }
        }
    }
}

C/C++题解代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
int n, m, k;
int matrix[150][150];
bool used[150];
vector<int> ans;
 
void dfs(int row, int col, int depth) {
    if (depth == n) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (!used[j]) {
                    ans.push_back(matrix[i][j]);
                }
            }
        }
        sort(ans.begin(), ans.end());
        return;
    }
 
    for (int i = col; i < m; i++) {
        if (!used[i]) {
            used[i] = true;
            dfs(row + 1, i + 1, depth + 1);
            used[i] = false;
        }
    }
}
 
int main() {
    cin >> n >> m >> k;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> matrix[i][j];
        }
    }
 
    dfs(0, 0, 0);
    cout << ans[k - 1] << endl;
 
    return 0;
}

JS题解代码


// 引入readline模块
const readline = require('readline');

// 创建readline接口实例
const rl = readline.createInterface({
  input: process.stdin, // 设置输入流
  output: process.stdout // 设置输出流
});

let n, m, K, mx; // 定义变量
let myMap = []; // 初始化二维数组

// 逐行读取输入
rl.on('line', (line) => {
  if (!n) { // 如果n未定义
    [n, m, K] = line.split(' ').map(Number); // 读取行数、列数和K值
    mx = 0; // 初始化mx
  } else {
    const row = line.split(' ').map(Number);
    myMap.push([0, ...row]);; // 读取二维数组数据
    mx = Math.max(mx, ...row); // 更新mx
  }
}).on('close', () => { // 读取完毕后执行
  console.log(solve(mx)); // 输出结果
});

// 二分第k大的值的大小
function solve(mx) {
  let l = 1, r = mx;
  let ans = 0;
    
  while (l <= r) {
    const mid = Math.floor((l + r) / 2);
    if (check(mid)) {
      ans = mid;
      r = mid - 1;
    } else {
      l = mid + 1;
    }
  }

  return ans;
}
// 将小于等于p的元素设为True,大于p的元素设为False,构建匹配图
function check(p) {
  const mp = myMap.map(row => row.map(val => val <= p));
  let ans = 0;
  const match = new Array(m + 1).fill(0);

  for (let i = 1; i <= n; i++) {
    const chw = new Array(m + 1).fill(true);
    if (findMuniu(i, mp, chw, match)) {
      ans++;
    }
  }
  return ans >= n - K + 1;
}
// 这里就是一个匈牙利匹配
function findMuniu(x, mp, chw, match) {
  // 在匹配图中寻找增广路径
  if (!mp[x] || mp[x].length !== m + 1) return false; // 检查mp[x]是否定义且长度正确

  for (let j = 1; j <= m; j++) {
    if (mp[x][j] && chw[j]) {
      chw[j] = false;
      if (match[j] === 0 || findMuniu(match[j], mp, chw, match)) {
        match[j] = x;
        return true;
      }
    }
  }
  return false;
}

四.代码讲解(Java&Python&C++&JS分别讲解)

Python题解代码解析:

  1. 导入itertools库中的combinations模块。
  2. 定义find_min_kth_largest函数,接受矩阵和K作为参数。
  3. 获取矩阵的行数和列数。
  4. 使用combinations生成所有包含N列的组合(N为矩阵的行数)。
  5. 遍历所有组合,对每个组合中的元素按降序排序,找到第K大的元素。
  6. 更新最小的第K大元素。
  7. 返回最小的第K大元素作为结果。

JAVA题解代码解析:

  1. 通过Scanner读取输入的N、M、K。
  2. 创建一个二维数组matrix来存储输入的矩阵。
  3. 调用findCombinations方法生成所有可能的组合,然后对每个组合中的元素进行排序。
  4. 将排序后的第K大的元素添加到结果集合中。
  5. 对结果集合进行排序,并输出排序后的第K大元素。

C/C++题解代码解析:

  1. 通过cin读取输入的N、M、K。
  2. 创建一个二维数组matrix来存储输入的矩阵。
  3. 调用dfs方法生成所有可能的组合,然后对每个组合中的元素进行排序。
  4. 将排序后的第K大的元素添加到结果向量ans中。
  5. ans进行排序,并输出排序后的第K大元素。

JS题解代码解析:

  1. 使用Node.js中的readline模块逐行读取输入。
  2. 解析输入的行数、列数、和K值。
  3. 构建一个二维数组myMap存储输入的矩阵。
  4. 使用二分查找法找到第K大的值,调用check函数进行判断。
  5. check函数中,构建匹配图,进行匈牙利匹配,判断是否存在至少n-K+1个匹配。
  6. 输出二分查找的结果。

寄语

标签:元素,matrix,Python,题解,OD,int,ans,排序
From: https://blog.csdn.net/mrdeam/article/details/137196158

相关文章

  • 文本统计分析【华为OD机试JAVA&Python&C++&JS题解】
    一.题目-文本统计分析有一个文件,包含以一定规则写作的文本,请统计文件中包含的文本数量规则如下文本以";“分隔,最后一条可以没有”;",但空文本不能算语句,比如"COMMANDA;;"只能算一条语句.注意,无字符/空白字符/制表符都算作"空"文本文本可以跨行,比如下面,......
  • [ABC347C] Ideal Holidays题解
    [ABC347C]IdealHolidays题解原题传送门原题传送门(洛谷)​ 题意翻译:​ 在\(AtCoder\)王国中,一个周有\(A+B\)天。其中在一周中,\([1,A]\)天是假日,\([A+1,B]\)天是工作日。​ 高桥有\(N\)个计划,第\(i\)个计划安排在\(i\)天后。他不知道今天是周几,但他想知道是否......
  • AT_abc347_d 的题解
    (一)数学题。根据\(C\)的值,可以得出\(x\)和\(y\)有\(s1+s\)个相同的数位和\(s2\)个不同的数位。\(s1\)是\(C\)的二进制中\(0\)的数量,\(s2\)是\(C\)的二进制中\(1\)的数量。\(x\)和\(y\)可以通过在开头放\(s\)个\(1\)的方式既不改变异或大小,又能凑到......
  • AT_abc347_e的题解
    (一)可能因为我太菜了,感觉D>E。用\(vis_i\)表示\(i\)是否出现,\(sum_i\)表示当前集合大小。用vector维护出现的区间的端点。将\(sum\)数组前缀和即可。(二)AC代码。#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intn,q,x,siz,sum[200010];......
  • AtCoder Beginner Contest 347
    ATlinkProblemAandB略。ProblemC按照模\(a+b\)分类,记录最大值和最小值,如果差值小于等于假期时间即可,否则还需要判断按照\(d_i=D_i\bmod(a+b)\)排序后相邻的两个是否满足条件。ProblemD分离出\(C\)的二进制位,然后对于每一位\(c_i>0\)尝试在\(A,B\)......
  • BZOJ4977 跳伞求生题解
    传送门题意:有\(n\)个队友和\(m\)个敌人,每个队友\(i\)有\(a_i\)颗子弹。敌人\(j\)有\(b_j\)颗子弹。队友击杀敌人,必须\(a_i>b_j\),然后会获得\(a_i-b_j+w_j\)的收益。(\(w_j\):每个敌人都有一个参数)每个队友只能打一个敌人,可以不打。求最大收益。【费用流模型......
  • pod退出过程和preStop
    1,用户发送删除pod的指令.2,API-Server服务器中的pod对象会随着时间的推移而更新,在宽限期内 terminationGracePeriodSeconds:30;默认是30秒,Pod被视为dead.3, 将pod标记为Terminating状态。4,(与第3步同时运行),kubelet在监控到pod对象转为Terminating状态的同时启动Pod关闭......
  • Python之Opencv进阶教程(2):统计图片灰度级别的像素数量
    1、什么是灰度像素数量在OpenCV中,可以使用**cv2.calcHist()**函数来计算图像的直方图。直方图是一种图形统计表,用于表示图像中每个灰度级别(或颜色通道)的像素数量或密度分布。以下是一个示例代码,演示了如何使用OpenCV计算和绘制图像的直方图:2、代码importcv2ascvimpor......
  • Python之Opencv进阶教程(1):图片模糊
    1、Opencv提供了多种模糊图片的方法加载原始未经模糊处理的图片importcv2ascvimg=cv.imread('../Resources/Photos/girl.jpg')cv.imshow('girl',img)1.1平均值关键代码#Averaging平均值a......
  • Python之Opencv教程(5):识别视频中的人脸
    1、识别效果2、识别代码importcv2ascvdefface_detect_demo(img):#将图片灰度gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)#加载特征数据face_detector=cv.CascadeClassifier("data//haarcascade_frontalface_alt.xml")fac......