华为校招机试 - 相似图片分类(20240410)

题目描述

小明想要处理一批图片,将相似的图片分类。

他首先对图片的特征采样,得到图片之间的相似度,然后按照以下规则判断图片是否可以归为一类:

  1. 相似度 > 0 表示两张图片相似
  2. 如果 A 和 B 相似,B 和 C 相似,但 A 和 C 不相似。那么认为A和C间接相似,可以把ABC归为一类,但不计算AC的相似度
  3. 如果 A 和所有其他图片都不相似,则 A 自己归为一类,相似度为0。

给定一个大小为 N × N 的矩阵 M,存储任意两张图片的相似度:

M[i][j] 即为第 i 个图片和第 j 个图片的相似度

请按照 “从大到小” 的顺序返回每个相似类中所有图片的相似度之和。

输入描述

第一行一个数 N,代表矩阵 M 中有 N 个图片,

下面跟着 N 行,每行有 N 列数据,空格分隔(为了显示整弃,空格可能为多个)代表 N 个图片之间的相似度。

约束:

  • 0 < N ≤ 900
  • 0 ≤ M[i][j] ≤ 100
  • 输入保证 M[i][i] =0,M[i][j]=M[j][i]

输出描述

每个相似类的相似度之和。

格式为:一行数字,分隔符为1个空格。

用例

输入5
0 0 50 0 0
0 0 0 25 0
50 0 0 0 15
0 25 0 0 0
0 0 15 0 0
输出65 25
说明

把1~5看成A,B,C,D,E,矩阵显示,

  • A和C相似度为50,
  • C和E的相似度为15,
  • B和D相似度为25。

划分出2个相似类,分别为

  • {A,C,E},相似度之和为65
  • {B,D},相似度之和25

排序输出相似度之和,结果为:65 25

题目解析

题目用例图示:

本题的图片相似归类可以使用并查集实现,关于并查集知识可以看下:

《算法训练营》进阶篇 01 并查集_哔哩哔哩_bilibili《算法训练营集训》进阶篇全套视频100集在这里: https://www.bilibili.com/cheese/play/ss6658 加QQ群281607840下载所有源码。《算法训练营》是一套没有编程经验的小白也能看懂的算法书,海量图解,实例丰富,图文并茂,全面系统搭建数据结构与算法知识体系,模块化逐一拆解算法问题。300道竞赛试题展示算法设计与实现的详细过程,培养算法思维,感受算法之美。, 视频播放量 17090、弹幕量 20、点赞数 428、投硬币枚数 265、收藏人数 588、转发人数 68, 视频作者 算法训练营, 作者简介 小玉老师,高级程序员,大数据分析师,课程咨询qq155170962,著作《算法训练营》(入门篇、进阶篇)《趣学算法》《趣学数据结构》,相关视频:全网最清晰的并查集讲解,算法讲解056【必备】并查集-上,图论——并查集(详细版),《算法训练营》进阶篇 04 最近公共祖先,[PTA] 朋友圈 并查集,【算法】并查集(Disjoint Set)[共3讲],算法动画秒懂并查集,《算法训练营》进阶篇 02 优先队列,并查集,并查集 画图详解+代码书写icon-default.png?t=N7T8https://www.bilibili.com/video/BV1VM4y1K7FV/?spm_id_from=333.337.search-card.all.click

以及练手题目:

LeetCode - 547 省份数量_return (this.fa[x]=this.find(this.fa[x]));-CSDN博客icon-default.png?t=N7T8https://fcqian.blog.csdn.net/article/details/127605092LeetCode - 200 岛屿数量_leetcode200岛屿数量-CSDN博客icon-default.png?t=N7T8https://fcqian.blog.csdn.net/article/details/127606569

本题难点并不在实现并查集,以及完成节点关联。

而是在节点关联完成后,如何统计每个连通图中所有图片的相似度之和?

如果是暴力求解的话,我们需要将连通图中图片两两判断,累加相似度之和。这种做法并不好。

更优的策略是,在我们遍历M矩阵时,如果M[i][j] > 0,则说明 i, j 图片相似,相似度为M[i][j]。

此时,我们需要做两个操作:

  • 完成 i,j 节点的关联,即并查集的union操作
  • 将此时的相似度 M[i][j] 记录到 i, j 关联后的新连通图的根上

另外,需要注意的是,在完成 i,j 关联之前

  • fa[i] 节点记录 i 所在连通图中所有图片的相似度之和
  • fa[j] 节点记录 j 所在连通图中所有图片的相似度之和

当完成关联后,i,j处于一个连通图中,假设fa[j] = fa[i],即将 j 所在子树并入了 i 所在子树,此时新连通图的根为fa[i]。

此时我们需要注意,由于我们期望将连通图中所有图片的相似度之和累计到根上,因此此时

  • fa[i] += fa[j]
  • fa[j] = 0

JS算法源码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;void (async function () {const n = parseInt(await readline());const matrix = [];for (let i = 0; i < n; i++) {matrix.push((await readline()).split(/\s+/).map(Number));}const ufs = new UnionFindSet(n);for (let i = 0; i < n; i++) {for (let j = i + 1; j < n; j++) {const similar = matrix[i][j];if (similar > 0) {// 合并两个子连通图为一个,将所有相似度之和(包括本次similar)全部转移到新连通图的根节点上ufs.union(i, j, similar);}}}// 按照 “从大到小” 的顺序返回每个相似类中所有图片的相似度之和const ans = ufs.sum.sort((a, b) => b - a).filter((a) => a > 0).join(" ");console.log(ans);
})();class UnionFindSet {constructor(n) {this.fa = new Array(n).fill(true).map((_, idx) => idx);// sum[i]表示以i为根的相似类中所有图片的相似度之和this.sum = new Array(n).fill(0);}find(x) {while (x !== this.fa[x]) {x = this.fa[x];}return x;}union(x, y, val) {let x_fa = this.find(x);let y_fa = this.find(y);// 本次新增的相似度,归到x_fa根或者y_fa根都可以this.sum[x_fa] += val;if (x_fa !== y_fa) {// 让Y_fa指向x_fa, 即x_fa成为新根this.fa[y_fa] = x_fa;// 此时y_fa上的相似度之和累计到新根x_fa上this.sum[x_fa] += this.sum[y_fa];// 累计完后,y_fa不在记录相似度this.sum[y_fa] = 0;}}
}

Java算法源码

import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();UnionFindSet ufs = new UnionFindSet(n);for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {int similar = sc.nextInt();// 避免重复ufs.union操作if (j <= i) continue;if (similar > 0) {// 合并两个子连通图为一个,将所有相似度之和(包括本次similar)全部转移到新连通图的根节点上ufs.union(i, j, similar);}}}StringJoiner sj = new StringJoiner(" ");// 升序Arrays.sort(ufs.sum);// 按照 “从大到小” 的顺序返回每个相似类中所有图片的相似度之和for (int i = n - 1; i >= 0; i--) {if(ufs.sum[i] == 0) break;sj.add(ufs.sum[i] + "");}System.out.println(sj);}
}// 并查集实现
class UnionFindSet {int[] fa;// sum[i]表示以i为根的相似类中所有图片的相似度之和int[] sum;public UnionFindSet(int n) {this.fa = new int[n];for (int i = 0; i < n; i++) fa[i] = i;this.sum = new int[n];}public int find(int x) {if (x != this.fa[x]) {this.fa[x] = this.find(this.fa[x]);return this.fa[x];}return x;}public void union(int x, int y, int val) {int x_fa = this.find(x);int y_fa = this.find(y);// 本次新增的相似度,归到x_fa根或者y_fa根都可以this.sum[x_fa] += val;if (x_fa != y_fa) {// 让Y_fa指向x_fa, 即x_fa成为新根this.fa[y_fa] = x_fa;// 此时y_fa上的相似度之和累计到新根x_fa上this.sum[x_fa] += this.sum[y_fa];// 累计完后,y_fa不在记录相似度this.sum[y_fa] = 0;}}
}

 

Python算法源码

import re# 并查集实现
class UnionFindSet:def __init__(self, n):self.fa = [i for i in range(n)]# sum[i]表示以i为根的相似类中所有图片的相似度之和self.sum = [0 for i in range(n)]def find(self, x):if x != self.fa[x]:self.fa[x] = self.find(self.fa[x])return self.fa[x]return xdef union(self, x, y, val):x_fa = self.find(x)y_fa = self.find(y)# 本次新增的相似度,归到x_fa根或者y_fa根都可以self.sum[x_fa] += valif x_fa != y_fa:# 让Y_fa指向x_fa, 即x_fa成为新根self.fa[y_fa] = x_fa# 此时y_fa上的相似度之和累计到新根x_fa上self.sum[x_fa] += self.sum[y_fa]# 累计完后,y_fa不在记录相似度self.sum[y_fa] = 0# 算法入口
def solution():n = int(input())matrix = []for _ in range(n):matrix.append(list(map(int, re.split(r"\s+", input()))))ufs = UnionFindSet(n)for i in range(n):for j in range(i + 1, n):similar = matrix[i][j]if similar > 0:# 合并两个子连通图为一个,将所有相似度之和(包括本次similar)全部转移到新连通图的根节点上ufs.union(i, j, similar)# 按照 “从大到小” 的顺序返回每个相似类中所有图片的相似度之和ufs.sum.sort(reverse=True)return " ".join(map(str, filter(lambda x: x > 0, ufs.sum)))# 算法调用
print(solution())

 

C算法源码

#include <stdio.h>
#include <stdlib.h>/** 并查集定义 **/
typedef struct {int *fa;// sum[i]表示以i为根的相似类中所有图片的相似度之和int *sum;
} UFS;UFS *new_UFS(int n) {UFS *ufs = (UFS *) malloc(sizeof(UFS));ufs->fa = (int *) malloc(sizeof(int) * n);ufs->sum = (int *) malloc(sizeof(int) * n);for (int i = 0; i < n; i++) {ufs->fa[i] = i;ufs->sum[i] = 0;}return ufs;
}int find_UFS(UFS *ufs, int x) {if (x != ufs->fa[x]) {ufs->fa[x] = find_UFS(ufs, ufs->fa[x]);return ufs->fa[x];}return x;
}void union_UFS(UFS *ufs, int x, int y, int val) {int x_fa = find_UFS(ufs, x);int y_fa = find_UFS(ufs, y);// 本次新增的相似度,归到x_fa根或者y_fa根都可以ufs->sum[x_fa] += val;if (x_fa != y_fa) {// 让Y_fa指向x_fa, 即x_fa成为新根ufs->fa[y_fa] = x_fa;// 此时y_fa上的相似度之和累计到新根x_fa上ufs->sum[x_fa] += ufs->sum[y_fa];// 累计完后,y_fa不在记录相似度ufs->sum[y_fa] = 0;}
}int cmp(const void *a, const void *b) {return *((int *) b) - *((int *) a);
}int main() {int n;scanf("%d", &n);UFS *ufs = new_UFS(n);for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {int similar;scanf("%d", &similar);if (j <= i) continue;if (similar > 0) {// 合并两个子连通图为一个,将所有相似度之和(包括本次similar)全部转移到新连通图的根节点上union_UFS(ufs, i, j, similar);}}}// 按照 “从大到小” 的顺序返回每个相似类中所有图片的相似度之和qsort(ufs->sum, n, sizeof(int), cmp);for (int i = 0; i < n; i++) {if (ufs->sum[i] == 0) break;printf("%d ", ufs->sum[i]);}puts("");return 0;
}

C++算法源码

#include <bits/stdc++.h>
using namespace std;// 并查集实现
class UnionFindSet {
public:int *fa;// sum[i]表示以i为根的相似类中所有图片的相似度之和int *sum;explicit UnionFindSet(int n) {fa = new int[n];sum = new int[n];for (int i = 0; i < n; i++) {fa[i] = i;sum[i] = 0;}};int find(int x) {if (x != fa[x]) {fa[x] = find(fa[x]);return fa[x];}return x;};void merge(int x, int y, int val) {int x_fa = find(x);int y_fa = find(y);// 本次新增的相似度,归到x_fa根或者y_fa根都可以sum[x_fa] += val;if (x_fa != y_fa) {// 让Y_fa指向x_fa, 即x_fa成为新根fa[y_fa] = x_fa;// 此时y_fa上的相似度之和累计到新根x_fa上sum[x_fa] += sum[y_fa];// 累计完后,y_fa不在记录相似度sum[y_fa] = 0;}};
};int main() {int n;cin >> n;UnionFindSet ufs(n);for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {int similar;cin >> similar;if (j <= i) continue;if (similar > 0) {// 合并两个子连通图为一个,将所有相似度之和(包括本次similar)全部转移到新连通图的根节点上ufs.merge(i, j, similar);}}}// 升序sort(ufs.sum, ufs.sum + n);// 按照 “从大到小” 的顺序返回每个相似类中所有图片的相似度之和for (int i = n - 1; i >= 0; i--) {if (ufs.sum[i] == 0) break;cout << ufs.sum[i] << " ";}cout << endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/807461.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于spring boot的大学生体质测试管理系统

基于spring boot的大学生体质测试管理系统设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 …

新鲜出炉!这一套二手平台管理系统,太牛了,直接领取【带源码】

​今天给大家分享一套基于SpringbootVue的二手平台管理系统源码&#xff0c;在实际项目中可以直接复用。(免费提供&#xff0c;文末自取) 一、系统运行图&#xff08;设计报告和接口文档&#xff09; 1、登陆页面 2、后台页面 3、设计报告包含接口文档 二、系统搭建视频教程 …

基于RKNN的YOLOv5安卓Demo

1.简介 基于RKNPU2 SDK 1.6.0版的安卓YOLOv5演示应用程序&#xff0c;选择图片进行对象检测并显示识别结果。 GitHub源码地址&#xff1a;https://github.com/shiyinghan/rknn-android-yolov5 2.实现过程 参考RKNN官方库RKNN Model Zoo提供的YOLOv5对象检测demo&#xff0c…

SQL注入sqli_labs靶场第三题

?id1and 11 and 11和?id1and 11 and 11进行测试如果11页面显示正常和原页面一样&#xff0c;并且12页面报错或者页面部分数据显示不正常&#xff0c;那么可以确定此处为字符型注入。 根据报错信息判断为单引号带括号注入 联合查询&#xff1a; 猜解列名 ?id1) order by 3-…

Java毕业设计 基于springboot vue撸宠平台 宠物系统

Java毕业设计 基于springboot vue撸宠平台 宠物系统 springboot撸宠平台 宠物系统 功能介绍 首页 图片轮播 用户或商家注册 用户或商家登录 登录验证码 店铺信息 店铺详情 店铺投诉 宠物信息 宠物详情 预订 退订 搜索 收藏 点赞 踩 评论 个人中心 更新信息 我的收藏 在线客服…

提升法律文书起草效率:AlphaGPT 助力律师快速生成诉讼和仲裁文件

法律文书起草对于法律专业人士而言是一项基础而关键的任务。无论是民事、刑事还是行政诉讼&#xff0c;以及仲裁案件&#xff0c;精确的法律文书撰写对于案件的成功至关重要。然而&#xff0c;这一过程往往既耗时又复杂&#xff0c;尤其是在处理复杂的案情和面对当事人难以理解…

syncfusion-diagram:demo1如何实现

xmlns:syncfusion"http://schemas.syncfusion.com/wpf" xmlns:stencil"clr-namespace:Syncfusion.UI.Xaml.Diagram.Stencil;assemblySyncfusion.SfDiagram.WPF"当我们进入syncfusion的diagram中&#xff0c;可以看到&#xff0c;一个非常炫酷的例子 不仅实…

为什么要部署IP SSL证书?怎么申请?

我们需要知道什么是IP SSL证书。SSL&#xff0c;全称为Secure Sockets Layer&#xff0c;即安全套接层&#xff0c;是为网络通信提供安全及数据完整性的一种安全协议。而IP SSL证书就是基于SSL协议的一种证书&#xff0c;它能够为网站和用户的数据传输提供加密处理&#xff0c;…

对称加密学习

对称加密是一种加密技术&#xff0c;它使用相同的密钥进行数据的加密和解密操作。这种加密方法因其高效性和速度优势&#xff0c;在数据加密领域得到了广泛的应用。 下面是两篇文章&#xff1a; AES加密学习-CSDN博客 加密算法学习-CSDN博客 推荐关注加密专栏&#xff1a; …

ThinkPHP审计(1) 不安全的SQL注入PHP反序列化链子phar利用简单的CMS审计实例

ThinkPHP代码审计(1) 不安全的SQL注入&PHP反序列化链子phar利用&简单的CMS审计实例 文章目录 ThinkPHP代码审计(1) 不安全的SQL注入&PHP反序列化链子phar利用&简单的CMS审计实例一.Thinkphp5不安全的SQL写法二.Thinkphp3 SQL注入三.Thinkphp链5.1.x结合phar实现…

Git可视化工具 - 推荐

概述 Git版本管理工具是我们日常开发中常用的工具&#xff0c;熟练使用它可以提高我们的工作效率。 当然老司机基本使用命令行的方式进行操作&#xff0c;新手可借助可视化工具来进行过渡&#xff0c;命令行与可视化工具结合使用来加深对Git的熟悉程度。 下面推荐两个较受欢迎…

STM32电机控制SDK实战

一、前言 本次测试基于ST开发板NUCLEO-F302R8&#xff0c;驱动板X-NUCLEO-IHM07M1&#xff0c;使用无刷直流电机BLDC实现FOC控制&#xff1b;采样三霍尔传感器检测电机转子位置&#xff1b;基于速度环闭环控制实现电机转动&#xff1b; 二、实战环境 软件环境&#xff1a; 1…

性能测试 —— 性能测试流程!

简介&#xff1a; 性能测试&#xff1a;利用工具模拟大量用户操作&#xff0c;验证系统承受的负载情况。 性能测试&#xff1a;利用工具模拟大量用户操作&#xff0c;验证系统承受的负载情况。 性能测试的目的&#xff1a;找到潜在的性能问题或瓶颈&#xff0c;分析并解决&am…

SpringCloudAlibaba-概述(一)

目录地址&#xff1a; SpringCloudAlibaba整合-CSDN博客 记录SpringCloudAlibaba的整合过程 一、简单概述一下项目情况 项目主要有4个模块和4个微服务&#xff1b; 项目结构如下&#xff1a; mall&#xff1a;父工程 -- common&#xff1a;公共组件&#xff0c;存放公用的实…

1、Qt UI控件 -- qucsdk

前言&#xff1a;Qt编写的自定义控件插件的sdk集合&#xff0c;包括了各个操作系统的动态库文件以及控件的头文件和sdk使用demo。类似于Wpf中的LivChart2控件库&#xff0c;都是一些编译好的控件&#xff0c;可以直接集成到项目中。该控件是飞扬青云大神多年前开发的&#xff0…

OV证书为什么更可信

在网络安全领域&#xff0c;SSL/TLS证书扮演着至关重要的角色&#xff0c;其中组织验证&#xff08;Organization Validation&#xff0c;简称OV&#xff09;证书以其深度验证机制和高度可信性脱颖而出。 OV证书为何更值得信赖&#xff0c;关键在于其严格的验证流程。 首先&am…

SOCKS代理概述

在网络技术的广阔领域中&#x1f310;&#xff0c;SOCKS代理是一个核心组件&#xff0c;它在提升在线隐私保护&#x1f6e1;️、实现匿名通信&#x1f3ad;以及突破网络访问限制&#x1f6ab;方面发挥着至关重要的作用。本文旨在深入探讨SOCKS代理的基础&#xff0c;包括其定义…

ai智能问答免费API接口

智能对话API接口&#xff0c;可以为网站或其他产品提供强大的智能交互功能&#xff0c;无需自行开发复杂的语义分析和自然语言处理算法。这使得开发者能够更专注于产品的核心功能和用户体验&#xff0c;加速产品上线速度并降低开发成本。 智能对话API接口的功能还包括对话内容…

DC40V降压恒压芯片H4120 40V转5V 3A 40V降压12V 车充降压恒压控制器

同步整流恒压芯片在现代电子设备中发挥着重要作用&#xff0c;为各种设备提供了稳定、高效的电源管理解决方案。 同步整流恒压芯片是一种电源管理芯片&#xff0c;它能够在不同电压输入条件下保持输出电压恒定。这种芯片广泛应用于各种电子设备中&#xff0c;如通讯设备、液晶…