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

想要精通算法和SQL的成长之路 - 课程表II

想要精通算法和SQL的成长之路 - 课程表

  • 前言
  • 一. 课程表II (拓扑排序)
    • 1.1 拓扑排序
    • 1.2 题解

前言

想要精通算法和SQL的成长之路 - 系列导航

一. 课程表II (拓扑排序)

原题链接
在这里插入图片描述

1.1 拓扑排序

核心知识:

  1. 拓扑排序是专门应用于有向图的算法。
  2. BFS的写法就叫拓扑排序,核心就是:让入度为0的节点入队。
  3. 拓扑排序的结果不唯一。
  4. 同时拓扑排序有一个重要的功能:能够检测有向图中是否存在环。

我们先分析一下本题:

  1. 先说下课程,课程有它自己的一个先后的依赖顺序。符合 “有向”
  2. 想要学习某个课程,它的前缀课程可能有多个。那么我们可以用 “度” 的概念去标识衡量。这里是入度。

先用图来解释下本次算法的核心方向(摘自leetcode题解):

  1. 在这里插入图片描述
  2. 在这里插入图片描述
  3. 在这里插入图片描述
  4. 在这里插入图片描述
  5. 在这里插入图片描述
  6. 在这里插入图片描述

说白了就是:

  1. 不断地找入度为0的节点,然后剔除。剔除的同时维护后续节点的入度数
  2. 以此类推。

1.2 题解

那么本题我们该如何解?我们一步步来,我们以numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]] 为例来说。官方解释:

  • 总共有 4 门课程。要学习课程 3,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 0 之后。
public int[] findOrder(int numCourses, int[][] prerequisites) {}

那么我们可以知道这个二维数组prerequisites中,第二个数字代表:”前缀“,第一个数字代表:”后缀“。[1,0] 用图表示就是:0->1同时我们还可以计算出,此时1这个节点的入度应该+1。因为0指向了1。

1.首先,我们要对入参做一个校验:

// 1. 先判断数组或者numCourses为空的情况
if (numCourses <= 0) {return new int[0];
}

2.我们需要遍历二维数组prerequisites中,拿到所有节点的入度以及这个拓扑图的结构。

  • 我们用inDegree[]数组表示各个节点的入度。
  • 用一个HashSet数组表示邻接表的结果。数组的索引代表的是节点的值。数组值(即HashMap)代表这个节点的所有后继节点。以0为例,它的后继节点有1和2。
// 2. 用inDegree[] 数组表示每个节点的入度数。
// 同时维护拓扑图的结构例如:0->1,0->2
HashSet<Integer>[] adj = new HashSet[numCourses];
// 初始化下
for (int i = 0; i < numCourses; i++) {adj[i] = new HashSet<>();
}
// 构建入度
int[] inDegree = new int[numCourses];
for (int[] p : prerequisites) {// 入度+1inDegree[p[0]]++;// 把当前节点的后继节点存储起来adj[p[1]].add(p[0]);
}

3.我们用一个队列,用来存储入度为0的节点。

// 3.准备个队列,存储入度为0的节点
LinkedList<Integer> queue = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {if (inDegree[i] == 0) {queue.offer(i);}
}

为啥要这一个步骤?如果发现没有入度为0的节点,说明啥,成环了,那本题就无解。如图:
在这里插入图片描述
4.如果存在入度为0的节点,我们开始往后递归,做2.1节的内容。

  • 先拿到入度为0的节点,删除它(把他放入结果集)。
  • 同时维护后继节点的入度。
  • 如果后继节点入度数-1后,为0。那么同样放入到队列中递归。
// 结果集
int[] res = new int[numCourses];
// 统计结果集中的个数
int count = 0;
while (!queue.isEmpty()) {// 入度为0的节点,我们弹出Integer head = queue.poll();// 放入结果集res[count++] = head;// 当前入度为0节点对应的后继节点。如果是0 --> 1,2HashSet<Integer> nextNodeList = adj[head];// 更新后继节点的入度for (Integer nextNode : nextNodeList) {// 对应的后继节点的入度要减1,inDegree[nextNode]--;// 如果入度-1后,为0了。再入队if (inDegree[nextNode] == 0) {queue.offer(nextNode);}}
}

最后,我们只需要关心结果集个数是否和题干中的numCourses一致。一致的话返回我们构建的结果集,否则本题为空解:

// 如果遍历完了,发现count数量和 numCourses一致,说明有一个正确的结果集
if (count == numCourses) {return res;
}
return new int[0];

最终完整代码如下:

public class Test210 {public int[] findOrder(int numCourses, int[][] prerequisites) {// 1. 先判断数组或者numCourses为空的情况if (numCourses <= 0) {return new int[0];}// 2. 用inDegree[] 数组表示每个节点的入度数。// 同时维护拓扑图的结构例如:0->1,0->2HashSet<Integer>[] adj = new HashSet[numCourses];// 初始化下for (int i = 0; i < numCourses; i++) {adj[i] = new HashSet<>();}// 构建入度int[] inDegree = new int[numCourses];for (int[] p : prerequisites) {// 入度+1inDegree[p[0]]++;// 把当前节点的后继节点存储起来adj[p[1]].add(p[0]);}// 3.准备个队列,存储入度为0的节点LinkedList<Integer> queue = new LinkedList<>();for (int i = 0; i < numCourses; i++) {if (inDegree[i] == 0) {queue.offer(i);}}// 结果集int[] res = new int[numCourses];// 统计结果集中的个数int count = 0;while (!queue.isEmpty()) {// 入度为0的节点,我们弹出Integer head = queue.poll();// 放入结果集res[count++] = head;// 当前入度为0节点对应的后继节点。如果是0 -- > 1,2HashSet<Integer> nextNodeList = adj[head];// 更新后继节点的入度for (Integer nextNode : nextNodeList) {// 对应的next节点的入度要减1,inDegree[nextNode]--;// 如果入度-1后,为0了。再入队if (inDegree[nextNode] == 0) {queue.offer(nextNode);}}}// 如果遍历完了,发现count数量和 numCourses一致,说明有一个正确的结果集if (count == numCourses) {return res;}return new int[0];}
}

这个题目,算是课程表系列的第二道了。第一道:207. 课程表,做法和上面一模一样,只不过返回数组的地方返回true/false即可。

相关文章:

想要精通算法和SQL的成长之路 - 课程表II

想要精通算法和SQL的成长之路 - 课程表 前言一. 课程表II &#xff08;拓扑排序&#xff09;1.1 拓扑排序1.2 题解 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 课程表II &#xff08;拓扑排序&#xff09; 原题链接 1.1 拓扑排序 核心知识&#xff1a; 拓扑排序是专…...

【sgGoogleTranslate】自定义组件:基于Vue.js用谷歌Google Translate翻译插件实现网站多国语言开发

sgGoogleTranslate源码 <template><div :id"$options.name"> </div> </template> <script> export default {name: "sgGoogleTranslate",props: ["languages", "currentLanguage"],data() {return {//…...

论文总结《A Closer Look at Few-shot Classification Again》

原文链接 A Closer Look at Few-shot Classification Again 摘要 这篇文章主要探讨了在少样本图像分类问题中&#xff0c;training algorithm 和 adaptation algorithm的相关性问题。给出了training algorithm和adaptation algorithm是完全不想关的&#xff0c;这意味着我们…...

Postman使用_参数设置和获取

文章目录 参数引用内置动态参数手动添加参数脚本设置参数脚本获取参数 参数就像变量一样&#xff0c;它可以是固定的值&#xff0c;也可以是变化的值&#xff0c;比如&#xff1a;会根据一些条件或其他参数进行变化。我们如果要使用该参数就需要引用它。 参数引用 引用动态参数…...

【SQL】优化SQL查询方法

优化SQK查询 一、避免全表扫描 1、where条件中少使用&#xff01; 或 <>操作符&#xff0c;引擎会放弃索引&#xff0c;进行全表扫描 2、in \or &#xff0c;用between 或 exist 代替in 3、where 对字段进行为空判断 4、where like ‘%条件’ 前置百分号 5、where …...

Linux-相关操作

2.2.2 Linux目录结构 /&#xff1a;根目录&#xff0c;一般根目录下只存放目录&#xff0c;在Linux下有且只有一个根目录。所有的东西都是从这里开始。当你在终端里输入“/home”&#xff0c;你其实是在告诉电脑&#xff0c;先从/&#xff08;根目录&#xff09;开始&#xf…...

二十、MySQL多表关系

1、概述 在项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求以及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种对应关系 2、多表关系分类 &#xff08;1&#xff0…...

HarmonyOS/OpenHarmony应用开发-DevEco Studio新建项目的整体说明

一、文件-新建-新建项目 二、传统应用形态与IDE自带的模板可供选用与免安装的元服与IDE中自带模板的选择 三、以元服务&#xff0c;远程模拟器为例说明IDE整体结构 1区是工程目录结构&#xff0c;是最基本的配置与开发路径等的认知。 2区是代码开发与修改区&#xff0c;是开发…...

去耦电路设计应用指南(三)磁珠/电感的噪声抑制

&#xff08;三&#xff09;磁珠/电感的噪声抑制 1. 电感1.1 电感频率特性 2. 铁氧体磁珠3. LC 型和 PI 型滤波 当去耦电容器不足以抑制电源噪声时&#xff0c;电感器&磁珠/ LC 滤波器的结合使用是很有效的。扼流线圈与铁氧体磁珠 是用于电源去耦电路很常见的电感器。 1. …...

Spring Bean的获取方式

参考https://juejin.cn/post/7251780545972994108?searchId2023091105493913AF7C1E3479BB943C80#heading-12 记录并补充 1.通过BeanFactoryAware package com.toryxu.demo1.beans;import org.springframework.beans.BeansException; import org.springframework.beans.facto…...

4795-2023 船用舱底水处理装置 学习记录

声明 本文是学习GB-T 4795-2023 船用舱底水处理装置. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件规定了船用舱底水处理装置(以下简称处理装置)中舱底水分离器(以下简称分离器)和舱底 水报警装置(以下简称报警装置)的要求、试验方法…...

[框架设计之道(二)]设备、任务设置及业务流程

[框架设计之道&#xff08;二&#xff09;]设备、任务设置及业务流程 说明 此文档是开发中对设备设置项的管理。因为硬件在使用的过程中涉及大量设置项&#xff0c;因此需要单独开一篇文档说明设备的设置和任务的设置。 一、设备设置 1.基础接口 /// <summary> /// 配置…...

Nuxt3+Vite批量引入图片

通过计算属性获取images文件夹所有层级下所有静态资源 <script name"MarketplaceHeader" setup lang"ts"> //批量导入静态资源图片 const importImage: any computed(() > (name: string, type png, folder images) > {const glob: Record…...

采用nodejs + socket.io实现简易聊天室功能(群聊 + 私聊)

项目演示 支持群聊以及私聊 项目代码 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport…...

消息队列(一):需求分析

为什么要做这样一个项目&#xff1f; 首先&#xff0c;我们在之前学习的时候&#xff0c;就认识了一下 生产者消费者模式&#xff0c;这样一个模式有两大好处&#xff1a; 解耦合 本来有个分布式系统&#xff0c;A服务器 调⽤ B服务器&#xff08;A给B发请求&#xff0c;B给A…...

ImageViewer技术实现细节

第1章 ImageViewer工具使用方法 1.1. 图像加载 1.1.1. 单图像加载 左上角菜单,“File”->“单图像”,或者Ctrl-S,弹出文件对话框,选择图像文件,当前支持bmp,png,jpg格式。 结果如下图所示: 1.1.2. 多图像加载 左上角菜单,“File”->“多图像”,或者Ctrl-M…...

MFC多文档程序,从菜单关闭一个文档和直接点击右上角的x效果不同

MFC多文档程序&#xff0c;从菜单关闭一个文档和直接点击右上角的x效果不同 若文档内容有修改&#xff0c;则前者会询问用户&#xff0c;是否保存修改&#xff1b;后者不保存修改直接关闭。 原因在于&#xff0c;从菜单关闭时&#xff0c;调用OnClose&#xff0c;一定会调用Sa…...

【数据结构】C++实现AVL平衡树

文章目录 1.AVL树的概念2.AVL树的实现AVL树结点的定义AVL树的插入AVL树的旋转左单旋右单旋左右双旋右左双旋插入代码 AVL树的验证AVL树的查找AVL树的修改AVL树的删除AVL树的性能 AVL树的代码测试 1.AVL树的概念 二叉搜索树虽然可以提高我们查找数据的效率&#xff0c;但如果插…...

图神经网络系列之序章

文章目录 一、为什么需要图神经网络&#xff1f;二、图的定义1.图的定义和种类2.一些关于图的重要概念2.1 子图2.2 连通图2.3 顶点的度、入度和出度2.4 边的权和网2.5 稠密图、稀疏图 3.图的存储结构3.1 邻接矩阵3.2 邻接表3.3 边集数组3.4 邻接多重表3.5 十字链表3.6 链式前向…...

Unity中 UI Shader的基本功能

文章目录 前言一、实现思路1、暴露一个 2D 类型的属性来接受UI的纹理2、设置shader的层级为TransParent半透明渲染层级&#xff0c;一般UI都是在这个渲染层级3、更改混合模式&#xff0c;是 UI 使用的纹理&#xff0c;该透明的地方透明 二、代码实现 前言 Unity中 UI Shader的…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...