当前位置: 首页 > news >正文

力扣题/图论/课程表

课程表

力扣原题

你这个学期必须选修 numCourses 门课程,记为 0numCourses - 1

在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi

例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false

示例 1:

输入:numCourses = 2, prerequisites = [[1,0]]
输出:true
解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。

示例 2:

输入:numCourses = 2, prerequisites = [[1,0],[0,1]]
输出:false
解释:总共有 2 门课程。学习课程 1 之前,你需要先完成​课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。

/*** @param {number} numCourses* @param {number[][]} prerequisites* @return {boolean}*/
var canFinish = function(numCourses, prerequisites) {// 构建节点关系    key: 当前节点, value:当前节点指向的所有节点const edges = buildEdges(prerequisites)let valid = trueconst visited = new Array(numCourses).fill(0)// 深度遍历,判断是否存在环function dfs(i) {const edge = edges[i]if(!edge) returnvisited[i] = 1 // 访问中for(const nextNode of edge) {if(visited[nextNode] === 0) {dfs(nextNode)if(!valid) return} else if(visited[nextNode] === 1) {// 存在环valid = false;return}}visited[i] = 2; // 已访问}for(let i = 0; i < numCourses; i++) {if(!visited[i]) {dfs(i)}}return valid
};// 构建边的关系
function buildEdges(prerequisites) {// 根据节点数量,初始化所有的节点的相邻的空数组(用于记录指向的节点)const edgeMap = {}for(const [node, preNode] of prerequisites) {if(!edgeMap[preNode]) {edgeMap[preNode] = []}edgeMap[preNode].push(node)}return edgeMap
}

解题思路

核心思路是构建有向图,然后深度遍历判断是否存在环存在环则无法进行拓扑排序,也说明无法完成所有课程的学习

  1. prerequisites中,每一项表示[课程, 先修课程]。遍历prerequisites转化为key先修课程value课程的数组。[构建有向图]
  2. 通过visited数组记录每个节点的访问状态,0:未访问,1:访问中,2:已访问,遍历所有节点,进行深度遍历dfs
  3. 深度遍历时,只需要判断,是否在遍历过程中,遇到访问中的节点即可,如果遇到访问中的节点,证明存在环。(如果不存在环,深度遍历过程中不可能访问到访问中的节点)
http://www.lryc.cn/news/429757.html

相关文章:

  • SQL进阶技巧:基于指定规则的缺失值填充问题
  • 【气象百科】光伏自动气象站的功能优势
  • 嵌入式AI快速入门课程-K510篇 (第二篇 Ubuntu的基础操作)
  • android13隐藏调节声音进度条下面的设置按钮
  • Java ArrayList和LinkedList
  • STM32F030行列式按键扫描
  • FPGA 综合笔记
  • Android MVVM框架详解与应用
  • 浅析KHD-厨帽检测算法从源码到实际应用的方案
  • ESXi里的FreeBSD装bhyve Ubuntu子系统,外网不通,子系统里无法ping通外面(使用NAT解决)
  • Connectionist Logic Systems and Hybrid Systems by Translation
  • 盘点数据摆渡的8种常用方式 最推荐哪一种?
  • 仿照ContentLoadingProgressBar 的特点在Android项目中自定义Loading对话框
  • 基于数据复杂度的数据库选型
  • QT基础知识5
  • C++中vector存放内置数据类型
  • shell编程:安装部署前常见环境检查
  • 思特科技:国家宝藏数字体验馆展现东方美学 让“文物活起来”
  • ES6笔记总结(Xmind格式):第二天
  • Kotlin 流flow、ShareFlow、StateFlow、Channel的解释与使用
  • 【个人学习】JVM(7):方法区概述、方法区内部结构、垃圾回收等
  • @Scheduled 定时任务自定义
  • 一种新颖的面试方式
  • 【Linux】生产消费模型实践 --- 基于信号量的环形队列
  • Science Robotics 与蜜蜂群互动的蜂窝型机器人系统
  • Vue 计算属性:优雅地处理数据逻辑
  • C++中`union`
  • Linux——网络(1)
  • 【五】阿伟开始学Kafka
  • Java—Arrays api