【面试题】面试官:判断图是否有环?_数据结构复试问题 有向图是否有环

    type: 'NODE';name: string;[x: string]: any;
};
[x: string]: any;

};
export type Data = Node | Edge;
复制代码


* 测试数据如下

const data: Data[] = [
{
id: ‘1’,
data: {
type: ‘NODE’,
name: ‘节点1’
}
},
{
id: ‘2’,
data: {
type: ‘NODE’,
name: ‘节点2’
}
},
{
id: ‘3’,
data: {
type: ‘NODE’,
name: ‘节点3’
}
},
{
id: ‘4’,
source: {
cell: ‘1’
},
target: {
cell: ‘2’
},
data: {
type: ‘EDGE’
}
},
{
id: ‘5’,
source: {
cell: ‘1’
},
target: {
cell: ‘3’
},
data: {
type: ‘EDGE’
}
}
];
复制代码


* 根据数据结构和测试数据`data:Data[]`,分为以下几个步骤:1. 获得边的集合和节点的集合。2. 根据边的集合和节点的集合,获得每个节点的有向邻居节点的集合。即以每个节点的为起点,通过边连接的下一个节点的集合。例如测试数据`节点1`,通过边`id4`和边`id5`,可以连接`节点2`和`节点3`,所以`节点1`的邻居节点是`节点2`和`节点3`,而`节点2`和`节点3`无有向邻居节点。3. 最后根据有向邻居节点的集合,判断是否有环。### 具体实现* 获得边的集合和节点的集合

const edges: Map<string, Edge> = new Map(), nodes: Map<string, Node> = new Map();
const idMapTargetNodes: Map<string, Node[]> = new Map();
const initGraph = () => {
for (const item of data) {
const { id } = item;
if (item.data.type === ‘EDGE’) {
edges.set(id, item as Edge);
} else {
nodes.set(id, item as Node);
}
}
};
复制代码


* 获取有向邻居节点的集合,这里的集合,可以优化成`id`。我为了方便处理,存储了节点

const idMapTargetNodes: Map<string, Node[]> = new Map();
const initTargetNodes = () => {
for (const [id, edge] of edges) {
const { source, target } = edge;
const sourceId = source.cell, targetId = target.cell;
if (nodes.has(sourceId) && nodes.has(targetId)) { //防止有空的边,即边的起点和终点不在节点的集合里
const targetNodes = idMapTargetNodes.get(sourceId);
if (Array.isArray(targetNodes)) {
targetNodes.push(nodes.get(targetId) as Node);
} else {
idMapTargetNodes.set(sourceId, [nodes.get(targetId) as Node]);
}
}
}
};
复制代码


* 最后判断是否有环,有两种方式:递归和循环。都是深度优先遍历。`execute`是遍历所有节点,`hasCycle`是把图的某个节点做为起点,判断是否有环。如果以所有节点为起点,都没有环,说明这个图没有环。1. 递归。`hasCycle`判断当前节点是否有环;`checked`是做优化,防止某些节点多次检查,回溯阶段,把当前节点加入`checked`;`visited`记录当前执行的`hasCycle`里是否访问过,如果访问过,就是有环。需要注意的是,每次执行`hasCycle`时,`visited`用的是一个变量,所以在回溯阶段需要把当前节点从`visited`里删除。

const checked: Set = new Set();
const hasCycle = (node: Node, visited: Set) => {
if (checked.has(node.id)) return false;
if (visited.has(node)) return true;
visited.add(node);
const { id } = node;
const targetNodes = idMapTargetNodes.get(id);
if (Array.isArray(targetNodes)) {
for (const item of targetNodes) {
if (hasCycle(item, visited)) return true;
}
}
checked.add(node.id);
visited.delete(node);
return false;
};
const execute = () => {
const visited: Set = new Set();
for (const [id, node] of nodes) {
if (hasCycle(node, visited)) return true;
checked.add(id);
}
return false;
};
复制代码

1. 循环。`checked`和递归时,作用一样,这里不做说明。`visited`是用来判断当前的节点是否遍历过,如果遍历过,就是有环。用循环实现深度优先遍历时,需要用`栈`来存储当前链路上的节点,即当前节点已经后代节点。并且从`栈`里面获取最后一个节点,作为当前遍历的节点。如果当前节点有向邻居节点不为空,就把有向邻居节点的最后一个节点拿出来压栈;如果有向邻居节点为空,就把当前的节点出栈。在压栈时,如果当前节点在`visited`里,就说明有环,如果没有就要把这个节点加入到`visited`。在出栈时,把当前节点从`visited`里删除掉,因为如果不删掉,当一个节点的多个邻居节点最终指向同一个节点时,会判断为有环。

const checked: Set = new Set();
const hasCycle = (node: Node) => {
const { id } = node;
if (checked.has(id)) return false;
const stack = [id];
const visited: Set = new Set();
visited.add(id);
while (stack.length > 0) {
const lastId = stack[stack.length - 1];
const targetNodes = idMapTargetNodes.get(lastId) || [];
if (targetNodes.length > 0) {

最后

前端CSS面试题文档,JavaScript面试题文档,Vue面试题文档,大厂面试题文档

.length > 0) {

最后

前端CSS面试题文档,JavaScript面试题文档,Vue面试题文档,大厂面试题文档

[外链图片转存中…(img-ze1QDx8k-1719237898712)]

[外链图片转存中…(img-pp9ZHRr7-1719237898713)]

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

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

相关文章

指针的相关知识

1.行指针 行指针 是一个指针&#xff0c; 指向的元素是一维数组。 存储行地址的指针变量&#xff0c;叫做行指针变量。形式如下&#xff1a; 存储类型 数据类型 (*指针变量名)[表达式&#xff1a;列数] ; 例如&#xff0c;int a[2][4]…

【linux kernel】一文总结linux的uevent机制

文章目录 一、kobject_uevent简介二、重要数据结构1、struct kobj_uevent_env2、struct kset_uevent_ops 三、kobject_uevent_env()详细剖析1、add_uevent_var()2、kobject_uevent_net_broadcast()3、call_usermodehelper_setup()4、call_usermodehelper_exec() 四、uevent_hel…

猫头虎 AI 前沿科技探索之路(持续更新):ChatGPT/GPT-4 科研应用、论文写作、数据分析与 AI 绘图及文生视频实战全攻略

猫头虎 AI 前沿科技探索之路(持续更新)&#xff1a;ChatGPT/GPT-4 科研应用、论文写作、数据分析与 AI 绘图及文生视频实战全攻略 背景介绍 随着人工智能技术的飞速发展&#xff0c;AI 的应用已经渗透到各个领域&#xff0c;从商业决策到医疗健康&#xff0c;再到日常生活中的…

猫头虎 分享已解决Error || Vanishing/Exploding Gradients: NaN values in gradients

猫头虎 分享已解决Error || Vanishing/Exploding Gradients: NaN values in gradients &#x1f42f; 摘要 &#x1f4c4; 大家好&#xff0c;我是猫头虎&#xff0c;一名专注于人工智能领域的博主。在AI开发中&#xff0c;我们经常会遇到各种各样的错误&#xff0c;其中Vani…

心理学|社会心理学——社会心理学单科作业(中科院)

一、单选题(第1-80小题,每题0.25分,共计40分。) 1、根据霍兰德的观点,社会心理学的形成期是在( )。 分值0.5分 A、社会哲学阶段 B、哲学思辨阶段 C、经验描述阶段 D、实证分析阶段 正确答案: C、经验描述阶段 2、社会行为公式B=f(P,E)中,B指( )。 分…

React+TS 从零开始教程(3):useState

源码链接&#xff1a;下载 在开始今天的内容之前呢&#xff0c;我们需要先看一个上一节遗留的问题&#xff0c;就是给属性设置默认值。 我们不难发现&#xff0c;这个defaultProps已经被废弃了&#xff0c;说明官方并不推荐这样做。其实&#xff0c;这个写法是之前类组件的时候…

国产编程—— 仓颉

应用 仓颉编程语言是一款由华为主导设计和实现的面向全场景智能的编程语言&#xff0c;主要应用于以下领域&#xff1a; 中文字符编码和文本数据处理&#xff1a;仓颉编程语言充分利用汉字的结构特点来设计编码&#xff0c;为开发者提供了一种高效的方式来编码、存储和处理中…

Kafka基础教程

Kafka基础教程 资料来源&#xff1a;Apache Kafka - Introduction (tutorialspoint.com) Apache Kafka起源于LinkedIn&#xff0c;后来在2011年成为一个开源Apache项目&#xff0c;然后在2012年成为一流的Apache项目。Kafka是用Scala和Java编写的。Apache Kafka是基于发布-订…

【Python/Pytorch 】-- K-means聚类算法

文章目录 文章目录 00 写在前面01 基于Python版本的K-means代码02 X-means方法03 最小二乘法简单理解04 贝叶斯信息准则 00 写在前面 时间演变聚类算法&#xff1a;将时间演变聚类算法用在去噪上&#xff0c;基本思想是&#xff0c;具有相似信号演化的体素具有相似的模型参数…

推荐一款AI修图工具,支持AI去水印,AI重绘,AI抠图...

不知道大家有没有这样的一个痛点&#xff0c;发现了一张不错的“素材”&#xff0c; 但是有水印&#xff0c;因此不能采用&#xff0c;但找来找去&#xff0c;还是觉得初见的那个素材不错&#xff0c;怎么办&#xff1f; 自己先办法呗。 二师兄发现了一款功能强大的AI修图工具…

使用Jetpack Compose为Android App创建自定义页面指示器

使用Jetpack Compose为Android App创建自定义页面指示器 在现代移动应用中&#xff0c;页面指示器在提供视觉导航提示方面发挥着重要作用&#xff0c;帮助用户理解其在应用内容中的当前位置。页面指示器特别适用于顺序展示内容的场景&#xff0c;如图片轮播、图像库、幻灯片放…

【Linux】Socket阻塞和非阻塞、同步与异步

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;Linux系列专栏&#xff1a;Linux基础 &#x1f525; 给大家…

java项目生成的api文档

生成Java项目API文档的方法 在进行Java项目开发时&#xff0c;编写良好的API文档对于团队合作和后续维护非常重要。生成API文档不仅可以提高团队协作效率&#xff0c;还可以方便其他开发人员了解项目结构和接口调用方式。在本文中&#xff0c;我们将介绍如何通过Java工具生成A…

WPF与Winform,你的选择是?

概述 在桌面应用的发展历程中&#xff0c;Winform和WPF作为微软推出的两大框架&#xff0c;各自承载着不同的设计理念和技术特色。Winform以其稳定、成熟的技术基础&#xff0c;长期占据着企业级应用开发的重要地位。而WPF&#xff0c;作为后来者&#xff0c;以其现代化的UI设计…

【ajax核心02】底层原理-Promise对象

目录 一&#xff1a;promise对象是什么 二&#xff1a;语法&#xff08;Promise使用步骤&#xff09; 三&#xff1a;Promise-三种状态 一&#xff1a;promise对象是什么 Promise 对象代表异步操作最终的完成&#xff08;或失败&#xff09;以及其结果值。 即Promise对象是…

CentOS7系统的软件源更改为阿里云源-3

要将您的CentOS系统的软件源更改为阿里云源&#xff0c;您可以按照以下步骤操作&#xff1a; 打开终端。 首先&#xff0c;备份原始的 CentOS-Base.repo 文件&#xff0c;以防出现问题时可以恢复&#xff1a; sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/Cen…

SAP系统中的总账会计(知识点总结)

总账会计 财务报表的组织结构 Company Code: 公司代码&#xff0c;an independent accounting entity&#xff0c; 一个独立的会计实体, 存储的数据为 T001。针对同一个公司代码会有Parallel Financial Reporting&#xff08;平行帐&#xff09;的要求&#xff0c;为了实现平…

基于springboot的图书管理系统源码数据库

当下&#xff0c;正处于信息化的时代&#xff0c;许多行业顺应时代的变化&#xff0c;结合使用计算机技术向数字化、信息化建设迈进。传统的图书管理信息管理模式&#xff0c;采用人工登记的方式保存相关数据&#xff0c;这种以人力为主的管理模式已然落后。本人结合使用主流的…

两个模型划分的瓦片数不同,可以把同一物体的两个模型(各有优缺点)就行融合修模吗?

答&#xff1a;网格大师可以针对模型瓦块名称&#xff0c;原点&#xff0c;大小不统一的数据进行融合 网格大师是一款能够解决实景三维模型空间参考、原点、瓦块大小不统一&#xff0c;重叠区域处理问题的工具“百宝箱”&#xff0c;集格式转换、坐标转换、轻量化、瓦片重划分…

uniapp接入微信小程序原生代码配置方案(优化版)

uniapp项目需要把微信小程序原生语法的功能代码嵌套过来&#xff0c;无需把原生代码转换为uniapp&#xff0c;可以配置拷贝的方式集成过来 1、拷贝代码包到src目录 2、vue.config.js中配置原生代码包直接拷贝到编译目录中 3、pages.json中配置分包目录&#xff0c;原生入口…