【LeetCode】210. 课程表 II——拓扑排序

题目链接:210. 课程表 II

题目描述:
现在你总共有 numCourses 门课需要选,记为 0 到 numCourses - 1。给你一个数组 prerequisites ,其中 prerequisites[i] = [ai, bi] ,表示在选修课程 ai 前 必须 先选修 bi 。

例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示:[0,1] 。
返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组 。
``
在这里插入图片描述
数据范围:
在这里插入图片描述

题解:从题目描述来看,很容易就知道是拓扑排序问题了,问题在于如何存图,如何解答,存图方式比较多,邻接表、邻接矩阵,解方面:遍历、搜索、以及队列都能完成该题的解答,实现方面很多时候还是会依赖一些语言特性,比如java、c++中有队列,可以将度为0的点放进队列中,每次出队一个去边,而在golang中数据结构支持相对匮乏,因此可以采用遍历或者搜索方式完成。

本次采用遍历方式,首先记录每个节点的入度,以及边的关系,遍历节点,每次选出一个度为0且未被选过的节点,然后去掉与这个节点相连的边,一共会执行numCourses次操作,当操作完后发现记录的答案中没有numCourses个节点,那么表示不能完成拓扑排序动作。

直接遍历:

func findOrder(numCourses int, prerequisites [][]int) []int {edges := make([][]int, numCourses, numCourses) // 存储边的关系for i := range edges {edges[i] = make([]int, numCourses, numCourses)}in := make([]int, numCourses, numCourses) // 记录入度for i := 0; i < len(prerequisites); i++ {a := prerequisites[i][0]b := prerequisites[i][1]edges[b][a] = 1 // 表示a指向b的边in[a]++}res := make([]int, 0, numCourses)// 遍历入度为0的点,然后去掉这些点相连的边for i := 0; i < numCourses; i++ { //共numCourses次操作,k := 0 // 记录当前寻找的入度为0的点for j := 0; j < numCourses; j++ { // 找一个度为0且未被遍历过的点if in[j] == 0 {res = append(res, j)in[j] = -1 // 记得标记为-1,已经找过的路径不再往下寻找k = jbreak}}for j := 0; j < numCourses; j++ {if edges[k][j] == 1 {edges[k][j] = -1 // 断开这条边in[j]-- //j点的入度-1}}}if len(res) != numCourses {return []int{}}return res
}

上述方式采用邻接矩阵方式来存储图,并且通过遍历方式来计算答案,虽然总共只操作n次,但每次都需要找寻度为0的节点,断开与该节点相连的边,这样会有很多次无效的遍历,浪费时间,因此,我们可以进行进一步的优化。

队列方式:

func findOrder(numCourses int, prerequisites [][]int) []int {edges := make([][]int, numCourses, numCourses) // 存储边的关系for i := range edges {edges[i] = make([]int, numCourses, numCourses)}in := make([]int, numCourses, numCourses) // 记录入度for i := 0; i < len(prerequisites); i++ {a := prerequisites[i][0]b := prerequisites[i][1]edges[b][a] = 1 // 表示a指向b的边in[a]++}queue := make([]int, 0, numCourses)for i := 0; i < numCourses; i++ {if in[i] == 0 {queue = append(queue, i)in[i] = -1}}res := make([]int, 0, numCourses) // 记录答案// 模拟一下队列for len(queue) > 0 {cur := queue[0]res = append(res, cur)queue = queue[1:] // 相当于除去这个元素// 从cur这个节点开始出发,断边for i := 0; i < numCourses; i++ {if edges[cur][i] == 1 { // 如果有边,则减少入度in[i]--edges[cur][i] = -1 // 断开这条边// 如果没有依赖边了,加入队列中if in[i] == 0 {queue = append(queue, i)}}}}if len(res) != numCourses {return []int{}}return res
}

当然,前面的存储我们都采用了邻接矩阵方式存储,找边的时候只能一个个遍历去寻找,不妨换一种思路,采用邻接表方式来存储,优化一下代码:

func findOrder(numCourses int, prerequisites [][]int) []int {edges := make([][]int, numCourses) // 存储边的关系fmt.Println(len(edges))in := make([]int, numCourses, numCourses) // 记录入度for i := 0; i < len(prerequisites); i++ {u := prerequisites[i][0]v := prerequisites[i][1]edges[v] = append(edges[v], u) // 记录v点指向的各个节点in[u]++}queue := make([]int, 0, numCourses)for i := 0; i < numCourses; i++ {if in[i] == 0 {queue = append(queue, i)}}res := make([]int, 0, numCourses) // 记录答案// 模拟一下队列for len(queue) > 0 {cur := queue[0]res = append(res, cur)queue = queue[1:]// 从cur这个节点开始出发,断边for _, v := range edges[cur] {in[v]--if in[v] == 0 {queue = append(queue, v)}}}if len(res) != numCourses {return []int{}}return res
}

这样,每个节点最多入队一次,也只会遍历m条边,假设有n个节点,那么时间复杂度为O(n+m)

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

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

相关文章

【Flowable】使用UEL整合Springboot从0到1(四)

前言 在前面我们介绍了Springboot简单使用了foleable以及flowableUI的安装和使用&#xff0c;在之前我们分配任务的处理人的时候都是通过Assignee去指定固定的人的。这在实际业务中是不合适的&#xff0c;我们希望在流程中动态的去解析每个节点的处理人&#xff0c;当前flowab…

9.12 C++作业

实现一个图形类&#xff08;Shape&#xff09;&#xff0c;包含受保护成员属性&#xff1a;周长、面积&#xff0c; 公共成员函数&#xff1a;特殊成员函数书写 定义一个圆形类&#xff08;Circle&#xff09;&#xff0c;继承自图形类&#xff0c;包含私有属性&#xff1a;半…

计算机网络TCP篇之流量控制

计算机网络TCP篇之流量控制 今天谈一谈我对于tcp流量控制的看法 在网络拓扑中如果发送方节点的发送速率大于接受方节点的接受速率&#xff0c;数据会不断在接受方的缓冲区累积&#xff0c;直到接受方的缓冲区满的时候&#xff0c;发送方继续发送数据&#xff0c;这时候接受方无…

算法通关村18关 | 回溯模板如何解决分割回文串问题

1. 分割回文串 题目 LeetCode131 分割回文串&#xff0c;给你一个字符串s&#xff0c;请你将s分割成一些字串&#xff0c;使每个字串都是回文串&#xff0c;返回s所有可能的分割方案。 回文串是正着和反着读都是一样的字符串。 思路 知道回溯的模板&#xff0c;用回溯的角度思…

用python实现音乐下载

前言 本文背景 最近对音乐比较有需求&#xff0c;想着用自己学的python来实现一下下载需求&#xff0c; 真的是拿着锤子在满世界找钉子&#xff0c;**文末附全部代码**声明&#xff1a; 本文仅作技术交流&#xff0c;禁止用于其他非法途径本文2023年9月15日是可用的&#xff…

AI Studio星河社区生产力实践:基于文心一言快速搭建知识库问答

还在寻找基于文心一言搭建本地知识库问答的方案吗&#xff1f;AI Studio星河社区带你实战演练&#xff08;支持私有化部署&#xff09;&#xff01; 相信对于大语言模型&#xff08;LLM&#xff09;有所涉猎的朋友&#xff0c;对于“老网红”知识库问答不会陌生。自从大模型爆…

树和二叉树

1、树的定义2、树的基本术语3、二叉树的定义4、二叉树的性质和存储结构5、满二叉树、完全二叉树**完全二叉树的性质** 6、二叉树的存储顺序存储结构链式存储结构 7、遍历二叉树演示8、二叉树相关算法&#xff08;1&#xff09;遍历二叉树递归算法实现&#xff08;2&#xff09;…

【LeetCode-简单题】26. 删除有序数组中的重复项

文章目录 题目方法一&#xff1a;快慢指针 题目 方法一&#xff1a;快慢指针 class Solution { //快慢指针public int removeDuplicates(int[] nums) {int fast 1;int slow 0;while(fast < nums.length){if(nums[fast] nums[fast-1]) fast;//若当前元素和之前元素相同 则…

[NLP]LLM---大模型指令微调中的“Prompt”

一 指令微调数据集形式太多 大家有没有分析过 prompt对模型训练或者推理的影响&#xff1f;之前推理的时候&#xff0c;发现不加训练的时候prompt&#xff0c;直接输入模型性能会变差的&#xff0c;这个倒是可以理解。假如不加prompt直接训练&#xff0c;是不是测试的时候不加…

将 Google Kubernetes Engine (GKE) 上稳定扩散的启动时间缩短 4 倍

Cloud Ace 是 Google Cloud 全球战略合作伙伴&#xff0c;在亚太地区、欧洲、南北美洲和非洲拥有二十多个办公室。Cloud Ace 在谷歌专业领域认证及专业知识目前排名全球第一位&#xff0c;并连续多次获得 Google Cloud 各类奖项。作为谷歌云托管服务商&#xff0c;我们提供谷歌…

构建健壮的Spring MVC应用:JSON响应与异常处理

目录 1. 引言 2. JSON 1. 轻量级和可读性 2. 易于编写和解析 3. 自描述性 4. 支持多种数据类型 5. 平台无关性 6. 易于集成 7. 社区支持和标准化 3. 高效处理异常 综合案例 异常处理方式一 异常处理方式二 异常处理方式三 1. 引言 探讨Spring MVC中关键的JSON数据…

【autodl/linux配环境心得:conda/本地配cuda,cudnn及pytorch心得】

linux配环境心得&#xff1a;conda/本地配cuda&#xff0c;cudnn及pytorch心得 我们服务器遇到的大多数找不到包的问题一&#xff0c;服务器安装cuda和cudnn使用conda在线安装cuda和cudnn使用conda进行本地安装检查conda安装的cuda和cudnn本地直接安装cuda和cudnn方法一&#x…

java高级:注解

目录 认识注解&自定义注解元注解解析注解注解的应用场景 认识注解&自定义注解 注解和反射一样&#xff0c;都是用来做框架的&#xff0c;我们这里学习注解的目的其实是为了以后学习框架或者做框架做铺垫的。 先来认识一下什么是注解&#xff1f;Java注解是代码中的特…

嵌入式学习笔记(31)异常向量表的编程处理

6.5.1像内存一样去访问异常向量表 &#xff08;1&#xff09;S5PV210的异常向量表可以改变&#xff08;在CP15协处理器中&#xff09;&#xff0c;以适应操作系统的需求。但是目前系统刚启动&#xff0c;此时DRAM尚未初始化&#xff0c;程序哦都市在iSRAM中运行。210在iSRAM中…

C++下基于粒子群算法解决TSP问题

粒子群优化算法求解TSP旅行商问题C&#xff08;2020.11.12&#xff09;_jing_zhong的博客-CSDN博客 混合粒子群算法&#xff08;PSO&#xff09;&#xff1a;C实现TSP问题 - 知乎 (zhihu.com) 一、原理 又是一个猜答案的算法&#xff0c;和遗传算法比较像&#xff0c;也是设…

入门人工智能 ——自然语言处理介绍,并使用 Python 进行文本情感分析(5)

入门人工智能 ——自然语言处理介绍&#xff0c;并使用 Python 进行文本情感分析&#xff08;5&#xff09;&#xff09; 入门人工智能 ——自然语言处理介绍&#xff0c;并使用 Python 进行文本情感分析介绍自然语言处理的挑战NLP的基本任务NLP的基本技术NLP的应用领域 使用 P…

FPGA的基础架构,什么是CLB?

本原创文章由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处 CLB是指可编程逻辑功能块&#xff08;Configurable Logic Blocks&#xff09;,顾名思义就是可编程的数字逻辑电路。CLB是FPGA内的三个基本逻辑单元。C…

与社交媒体结合:视频直播美颜sdk在社交平台上的应用

为了让直播内容更吸引人&#xff0c;视频直播美颜sdk&#xff08;Software Development Kit&#xff09;正逐渐崭露头角&#xff0c;为社交媒体用户提供了卓越的美颜效果和互动体验。 一、什么是视频直播美颜sdk&#xff1f; 在深入讨论如何将视频直播美颜sdk整合到社交媒体平…

CSS元素浮动

概述 浮动简介 在最初&#xff0c;浮动是用来实现文字环绕图片效果的&#xff0c;现在浮动是主流的页面布局方式之一。 元素浮动后的特点 脱离文档流。不管浮动前是什么元素&#xff0c;浮动后&#xff0c;默认宽与高都是被内容撑开的&#xff08;尽可能小&#xff09;&am…

时序分解 | MATLAB实现基于小波分解信号分解分量可视化

时序分解 | MATLAB实现基于小波分解信号分解分量可视化 目录 时序分解 | MATLAB实现基于小波分解信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于小波分解的分量可视化&#xff0c;MATLAB编程程序&#xff0c;用于将信号分解成不同尺度和频率的子信…