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

地址:前端面试题库  web前端面试题库 VS java后端面试题库大全

背景

  • 简单介绍需求,通过可视化流程配置答题流程,题目与题目之间用线连接,箭头的方向代表下一个题目。回答完当前题目,根据不同的条件,跳到下一题;如果题目流程中有循环,会导致答题流程无法结束,所以需要校验题目的流程中不能有循环。
  • 下面的是有循环,不符合条件

  • 下面的是无循环,符合条件

技术方案

  • 根据需求,我们把题目的流程配置抽象成有向图,题目是节点,题目之间的连线是边。
  • 需求里的有无循环,最终可以转换成图是否有环的问题。从图的某个节点作为起点,根据边的方向出发跳到下一个节点,最终是否回到起点。如果回到起点,就是有循环、有环,否则是无循环、无环。
  • 去除题目和各种条件等无关的结构,数据结构如下。
//边
export interface Edge {
    id: string;
    source: {
        cell: string;   //这条边的起点的id
        [x: string]: any;
    };
    target: {
        cell: string;   //这条边的终点的id
        [x: string]: any;
    };
    data: {
        type: 'EDGE',
        [x: string]: any;
    }
    [x: string]: any;
};
//节点
export interface Node {
    id: string;
    data: {
        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);


### 最后

在面试前我花了三个月时间刷了很多大厂面试题,最近做了一个整理并分类,主要内容包括html,css,JavaScript,ES6,计算机网络,浏览器,工程化,模块化,Node.js,框架,数据结构,性能优化,项目等等。



包含了腾讯、字节跳动、小米、阿里、滴滴、美团、58、拼多多、360、新浪、搜狐等一线互联网公司面试被问到的题目,涵盖了初中级前端技术点。

*   HTML5新特性,语义化

*   浏览器的标准模式和怪异模式

*   xhtml和html的区别

*   使用data-的好处

*   meta标签

*   canvas

*   HTML废弃的标签

*   IE6 bug,和一些定位写法

*   css js放置位置和原因

*   什么是渐进式渲染

*   html模板语言

*   meta viewport原理

![](https://img-blog.csdnimg.cn/img_convert/64590c67cb47cd552a892ba710477f64.png)

*   **[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.youkuaiyun.com/topics/618166371)**

![](https://img-blog.csdnimg.cn/img_convert/17fdfcb90fad04acc5e7273d1f853880.png)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值