Python算法题集_图论(课程表)
Python算法题集_课程表
- 题207:课程表
- 1. 示例说明
- 2. 题目解析
- - 题意分解
- - 优化思路
- - 测量工具
- 3. 代码展开
- 1) 标准求解【循环+递归+全算】
- 2) 改进版一【循环+递归+缓存】
- 3) 改进版二【循环+递归+缓存+反向计算】
- 4) 改进版三【迭代剥离+计数器检测】
- 4. 最优算法
- 5. 相关资源
本文为Python算法题集之一的代码示例
题207:课程表
1. 示例说明
你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 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 。这是不可能的。
提示:
1 <= numCourses <= 20000 <= prerequisites.length <= 5000prerequisites[i].length == 20 <= ai, bi < numCoursesprerequisites[i]中的所有课程对 互不相同
2. 题目解析
- 题意分解
- 本题是计算是否会出现无法学习的课程,这种课程的特点是前置课程出现环路,比如A课程的前置课程B的前置课程为A课程
- 本题必须进行课程遍历,每个课程都需要检测是否出现环路
- 基本的设计思路是循环+递归,循环遍历课程,递归检测环路
- 优化思路
-
通常优化:减少循环层次
-
通常优化:增加分支,减少计算集
-
通常优化:采用内置算法来提升计算速度
-
分析题目特点,分析最优解
-
如果一个课程已经检测没有出现环路,则前置课程检测到此课程就不用继续检测下去,减少计算量
-
可以研究迭代法实现科目检测
-
- 测量工具
- 本地化测试说明:LeetCode网站测试运行时数据波动很大【可把页面视为功能测试】,因此需要本地化测试解决数据波动问题
CheckFuncPerf(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块- 本题超时测试用例较难生成,已经保存为文本文件,本次测试结果详见章节【最优算法】,测试用例文件包含在【相关资源】中
3. 代码展开
1) 标准求解【循环+递归+全算】
循环遍历课程,递归检测环路,能算尽算,不出所料,功能测试就已超时
页面功能测试,未能通关,超时失败
import CheckFuncPerf as cfpclass Solution:def canFinish_base(self, numCourses, prerequisites):list_graph = [[] for x in range(numCourses)]for a, b in prerequisites:list_graph[a].append(b)def dfs_checkring(visited, pres):if not pres:return Trueresult = Truefor course in pres:if course in visited:return Falseresult &= dfs_checkring(visited + [course], list_graph[course])return resultreturn all(dfs_checkring([i], pres) for i, pres in enumerate(list_graph))print(f'prerequisites count of the Courses = {len(check_prerequisites)}')
result = cfp.getTimeMemoryStr(Solution.canFinish_base, aSolution, 50000, check_prerequisites)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
prerequisites count of the Courses = 49999
函数 canFinish_base 的运行时间为 50813.51 ms;内存使用量为 7264.00 KB 执行结果 = True
2) 改进版一【循环+递归+缓存】
循环遍历课程,递归检测环路,缓存已经计算的课程环路结果
页面功能测试,勉强通过,超过11%
import CheckFuncPerf as cfpclass Solution:def canFinish_ext1(self, numCourses: int, prerequisites):list_graph = [[] for x in range(numCourses)]for a, b in prerequisites:list_graph[a].append(b)learned = [0] * numCoursesdef dfs_checkring(visited, pres):if not pres:return Trueresult = Truefor course in pres:if course in visited:return Falseif learned[course] > 0:continuelearned[course] = 1result &= dfs_checkring(visited + [course], list_graph[course])return resultfor iIdx, pres in enumerate(list_graph):if learned[iIdx] > 0:continueresult = dfs_checkring([iIdx], pres)if not result:return Falselearned[iIdx] = 1return Trueprint(f'prerequisites count of the Courses = {len(check_prerequisites)}')
result = cfp.getTimeMemoryStr(Solution.canFinish_base, aSolution, 50000, check_prerequisites)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
prerequisites count of the Courses = 49999
函数 canFinish_ext1 的运行时间为 66.02 ms;内存使用量为 6112.00 KB 执行结果 = True
3) 改进版二【循环+递归+缓存+反向计算】
循环遍历课程,递归检测环路,但是检测环路修改为从前置科目开始计算此科目的后置科目是否出现环路
页面功能测试,性能良好,超过88%
import CheckFuncPerf as cfpclass Solution:def canFinish_ext2(self, numCourses, prerequisites):def dfs_checkring(iIdx, list_graph, ringflags):if ringflags[iIdx] == -1:return Trueif ringflags[iIdx] == 1:return Falseringflags[iIdx] = 1for jIdx in list_graph[iIdx]:if not dfs_checkring(jIdx, list_graph, ringflags):return Falseringflags[iIdx] = -1return Truelist_graph = [[] for x in range(numCourses) ]list_flags = [0 for x in range(numCourses)]for a, b in prerequisites:list_graph[b].append(a)for iIdx in range(numCourses):if not dfs_checkring(iIdx, list_graph, list_flags):return Falsereturn Trueprint(f'prerequisites count of the Courses = {len(check_prerequisites)}')
result = cfp.getTimeMemoryStr(Solution.canFinish_ext2, aSolution, 50000, check_prerequisites)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
prerequisites count of the Courses = 49999
函数 canFinish_ext2 的运行时间为 80.01 ms;内存使用量为 520.00 KB 执行结果 = True
4) 改进版三【迭代剥离+计数器检测】
特殊的迭代思路
- 首先必须存在没有任何前置的科目,否则第一门科目都没有办法学习,直接返回False;由此可建立没有前置科目的队列
- 迭代没有前置科目的队列,逐步剥离此科目后置科目的计数器,如果后置科目的前置计数器清零,则作为无前置科目放入队列
- 迭代完毕后检测有效科目数量是否达标
页面功能测试,马马虎虎,超过55%
import CheckFuncPerf as cfpclass Solution:def canFinish_ext3(self, numCourses, prerequisites):from collections import deque, defaultdictdeque_graph = defaultdict(list)learned = [0] * numCoursesfor course, visited in prerequisites:deque_graph[visited].append(course)learned[course] += 1queue = deque([x for x in range(numCourses) if learned[x] == 0])processed_courses = 0while queue:visited = queue.popleft()processed_courses += 1for course in deque_graph[visited]:learned[course] -= 1if learned[course] == 0:queue.append(course)return processed_courses >= numCoursesprint(f'prerequisites count of the Courses = {len(check_prerequisites)}')
result = cfp.getTimeMemoryStr(Solution.canFinish_ext3, aSolution, 50000, check_prerequisites)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 运行结果
prerequisites count of the Courses = 49999
函数 canFinish_ext3 的运行时间为 84.02 ms;内存使用量为 584.00 KB 执行结果 = True
4. 最优算法
根据本地日志分析,最优算法为第2种方式【循环+递归+缓存】canFinish_ext1
由于四段代码思路一致,主要是使用的数据结构不同,因此经验推出以下结论:
- 在作为队列使用时【先进先出】,
deque性能远远高于list - 迭代器循环优于循环中进行异常检测
- 下标循环和枚举循环性能基本一致
inumCourses = 50000
aSolution = Solution()
testcase_big = open(r'testcase/hot53_big5W.txt', mode='r', encoding='utf-8').read()
testcase_big = testcase_big.replace('[', '')
tmpItems = testcase_big.split(']')
check_pre = []
for aItem in tmpItems:tmpcurpre = aItem.split(',')if len(tmpcurpre) == 2:check_pre.append([int(tmpcurpre[0]), int(tmpcurpre[1])])
check_prerequisites = check_pre
print(f'prerequisites count of the Courses = {len(check_prerequisites)}')
result = cfp.getTimeMemoryStr(Solution.canFinish_base, aSolution, inumCourses, check_prerequisites)
print(result['msg'], '执行结果 = {}'.format(result['result']))
result = cfp.getTimeMemoryStr(Solution.canFinish_ext1, aSolution, inumCourses, check_prerequisites)
print(result['msg'], '执行结果 = {}'.format(result['result']))
result = cfp.getTimeMemoryStr(Solution.canFinish_ext2, aSolution, inumCourses, check_prerequisites)
print(result['msg'], '执行结果 = {}'.format(result['result']))
result = cfp.getTimeMemoryStr(Solution.canFinish_ext3, aSolution, inumCourses, check_prerequisites)
print(result['msg'], '执行结果 = {}'.format(result['result']))# 算法本地速度实测比较
prerequisites count of the Courses = 49999
函数 canFinish_base 的运行时间为 50813.51 ms;内存使用量为 7264.00 KB 执行结果 = True
函数 canFinish_ext1 的运行时间为 66.02 ms;内存使用量为 6112.00 KB 执行结果 = True
函数 canFinish_ext2 的运行时间为 80.01 ms;内存使用量为 520.00 KB 执行结果 = True
函数 canFinish_ext3 的运行时间为 84.02 ms;内存使用量为 584.00 KB 执行结果 = True
5. 相关资源
本文代码已上传到CSDN,地址:Python算法题源代码_LeetCode(力扣)_课程表
一日练,一日功,一日不练十日空
may the odds be ever in your favor ~
相关文章:
Python算法题集_图论(课程表)
Python算法题集_课程表 题207:课程表1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【循环递归全算】2) 改进版一【循环递归缓存】3) 改进版二【循环递归缓存反向计算】4) 改进版三【迭代剥离计数器检测】 4. 最优算法5. 相关资源 本…...
视频评论挖掘软件|抖音视频下载工具
针对抖音视频下载的需求,我们开发了一款功能强大的工具,旨在解决用户在获取抖音视频时需要逐个复制链接、下载的繁琐问题。我们希望用户能够通过简单的关键词搜索,实现自动批量抓取视频,并根据需要进行选择性批量下载。因此&#…...
Linux学习方法-框架学习法——Linux驱动架构的演进
配套视频学习链接:https://www.bilibili.com/video/BV1HE411w7by?p4&vd_sourced488bc722b90657aaa06a1e8647eddfc 目录 Linux驱动演进的过程 Linux驱动的原始架构(Linux V2.4) 平台总线架构(platform) Linux设备树 Linux驱动演进的趋势 Linux驱动演进的过程…...
Spring Boot基础面试问题(一)
上篇文章中10个Spring Boot面试问题的标准答案: 什么是Spring Boot?它与Spring框架有什么区别? 标准回答:Spring Boot是基于Spring框架的快速开发框架,它简化了Spring应用程序的搭建和配置过程,提供了一套自…...
电路设计(28)——交通灯控制器的multisim仿真
1.功能设定 南北、东西两道的红灯时间、绿灯时间均为24S,数码管显示倒计时。在绿灯的最后5S内,黄灯闪烁。有夜间模式:按下按键进入夜间模式。在夜间模式下,数码管显示计数最大值,两个方向的黄灯不停闪烁。 2.电路设计 …...
【Docker】免费使用的腾讯云容器镜像服务
需要云服务器等云产品来学习Linux可以移步/-->腾讯云<--/官网,轻量型云服务器低至112元/年,新用户首次下单享超低折扣。 目录 1、设置密码 2、登录实例(sudo docker login xxxxxx) 3、新建命名空间(每个命名空…...
如何让qml使用opengl es
要让 QML 使用 OpenGL ES,您需要确保项目配置正确,并在应用程序中使用 QSurfaceFormat 来设置 OpenGL ES 渲染。 以下是一些步骤来配置 QML 使用 OpenGL ES: 1、项目配置:在您的项目配置文件(例如 .pro 文件…...
金航标电子位于广西柳州鹿寨县天线生产基地于大年正月初九开工了!!
金航标电子位于广西柳州鹿寨县天线生产基地于大年正月初九开工了!!!金航标kinghelm( http://www.kinghelm.com.cn )总部位于中国深圳市,兼顾技术、成本、管理、效率和可持续发展。东莞塘厦实验室全电波暗…...
FlinkCDC详解
1、FlinkCDC是什么 1.1 CDC是什么 CDC是Chanage Data Capture(数据变更捕获)的简称。其核心原理就是监测并捕获数据库的变动(例如增删改),将这些变更按照发生顺序捕获,将捕获到的数据,写入数据…...
力扣代码学习日记六
Problem: 66. 加一 思路 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。 你可以假设除了整数 0 之外,这个整数不会以零开头。 示例 1: 输…...
「Python系列」Python标准库
文章目录 一、 os 模块:文件和目录操作二、 sys 模块:与Python解释器交互三、 datetime 模块:日期和时间处理四、 json 模块:处理JSON数据五、 re 模块:正则表达式六、 time模块1. 获取当前时间2. 延迟执行(…...
虚拟列表【vue】等高虚拟列表/非等高虚拟列表
文章目录 1、等高虚拟列表2、非等高虚拟列表 1、等高虚拟列表 参考文章1 参考文章2 <!-- eslint-disable vue/multi-word-component-names --> <template><divclass"waterfall-wrapper"ref"waterfallWrapperRef"scroll"handleScro…...
【MySQL】如何理解索引(高频面试点)
一、前言 首先这个博客会介绍一些关于MySQL中索引的基本内容以及一些基本的语法,当然里面也会有些常见的面试题的解答。 二、关于索引 1、概念 索引是一种能够帮助MySQL高效的去磁盘检索数据的一种数据结构。在MySQL的Innodb存储引擎中呢,采用的是B树的…...
NXP实战笔记(四):S32K3xx如何产生中心对称三相六路波形
目录 1、概述 1.1、理论基础 2、RTD实现 2.1、Emios时基配置 2.1.1、EmiosMcl 2.1.2、EmiosCommon 2.2、Emios PWM配置 2.3、TRGMUX 2.4、LCU 2.5、外设信号配置 3、代码实现 4、测试结果 1、概述 电机控制中需要产生三相六路SVPWM进行占空比与周期调制,怎么通过RT…...
关于uniapp H5应用无法在触摸屏正常显示的处理办法
关于uniapp H5应用无法在触摸屏正常显示的处理办法 1、问题2、处理3、建议 1、问题 前几天, 客户反馈在安卓触摸大屏上无法正确打开web系统(uni-app vue3开发的h5 应用),有些页面显示不出内容。该应用在 pc 端和手机端都可以正常…...
Stable Diffusion 3 发布,AI生图效果,再次到达全新里程碑!
AI生图效果,再次到达全新里程碑! Prompt:Epic anime artwork of a wizard atop a mountain at night casting a cosmic spell into the dark sky that says "Stable Diffusion 3" made out of colorful energy 提示(意译…...
单例模式怎样实现单例(独例)?
在类定义中加入私有属性 __init__flag Ture,在随后的初始化处理中,判断该属性为真时进行相应的初始化操作,否则,跳过相应的初始化操作。这个机制,保证在进行后续的调用时,不再占用额外的内存开销。 当然了,…...
MySQL——基础内容
目录 第01章_数据库概述 关系型数据库(RDBMS)——表、关系模型 非关系型数据库(非RDBMS) 表、记录、字段 表的关联关系 一对一关联 一对多关系 多对多 自我引用 第02章_MySQL环境搭建 登录命令 常用命令 show databases; create database use 数据库名 show tables 第03章…...
node 之 初步认识
思考:为什么JavaScript可以在浏览器中被执行 代执行的js代码——JavaScript解析引擎 不同的浏览器使用不同的JavaScript解析引擎 Chrome 浏览器 》 V8 Firefox浏览器 》OdinMonkey(奥丁猴) Safri浏览器 》JSCore IE浏览器 》Chakra(查克拉) e…...
css复习
盒模型相关: border:1px solid red (没有顺序) 单元格的border会发生重叠,如果不想要重叠设置 border-collapse:collapse (表示相邻边框合并在一起) padding padding影响盒子大小的好处使用 margin应用: 行内或行内块元素水…...
革新性B站用户分析工具:智能解析评论区用户背景的终极方案
革新性B站用户分析工具:智能解析评论区用户背景的终极方案 【免费下载链接】bilibili-comment-checker B站评论区自动标注成分,支持动态和关注识别以及手动输入 UID 识别 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-comment-checker …...
安装即实战,用快马平台生成集成openclaw的数据采集与分析示例项目
最近在做一个数据采集相关的项目,需要用到openclaw这个工具。说实话,刚开始安装和集成的时候踩了不少坑,后来发现InsCode(快马)平台可以一键生成完整的实战项目,简直不要太方便。今天就把我的经验分享给大家,希望能帮到…...
别再为GEO数据注释发愁了!三种方法(TXT/Soft/R包)保姆级代码实战
GEO数据注释实战指南:TXT/Soft/R包三种方法全解析 刚接触生物信息学的研究者常常会在GEO数据分析的第一步就卡壳——面对五花八门的注释文件格式,如何准确高效地将探针ID转换为基因Symbol?这个问题看似简单,实则暗藏玄机。我曾见过…...
SAP工单组件批量添加技巧:CO_XT_COMPONENT_ADD与CO_XT_ORDER_PREPARE_COMMIT组合使用教程
SAP工单组件批量添加实战:CO_XT_COMPONENT_ADD与CO_XT_ORDER_PREPARE_COMMIT深度解析 在SAP生产订单管理中,批量添加组件是制造企业常见的需求场景。当面对数百甚至上千个工单组件需要同时维护时,传统GUI操作不仅效率低下,还容易出…...
C++协程(C++20)原理剖析:co_await的实现机制
C20引入的协程机制为异步编程带来了革命性变化,其中co_await作为核心操作符,其实现机制值得深入探讨。本文将剖析co_await背后的魔法,揭示协程如何通过挂起与恢复实现高效异步。 协程三要素解析 协程由promise对象、协程句柄和协程状态三部…...
OpenClaw对接Qwen3-VL:30B:个人AI助手搭建全指南
OpenClaw对接Qwen3-VL:30B:个人AI助手搭建全指南 1. 为什么选择这个组合? 去年冬天,我偶然在GitHub上发现了OpenClaw这个项目。当时我正在为团队寻找一个既能处理文档又能执行自动化任务的解决方案。试过几个商业产品后,要么功能…...
League Toolkit:重新定义英雄联盟游戏体验的智能辅助工具集
League Toolkit:重新定义英雄联盟游戏体验的智能辅助工具集 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 在快节奏的…...
保姆级教程:用Code Blocks搞定中科蓝讯AB5768E蓝牙音响SDK开发环境(附资源包)
从零构建中科蓝讯AB5768E蓝牙音响开发环境:原理剖析与实战避坑指南 刚拿到中科蓝讯K12开发板时,面对陌生的AB5768E芯片和配套SDK,不少开发者会陷入"环境配置地狱"——明明按照文档操作,却总是卡在编译器报错、路径缺失等…...
基于双向DC - DC变换器(DAB)的储能系统控制仿真
Matlab/Simulink仿真模型,基于双向DC-DC变换器(双有源桥变换器DAB)的储能系统控制仿真模型,采用电压电流双PI闭环控制策略,单移相控制,在母线电压受到外界干扰的情况下,通过控制电池的充电和放电…...
从标准到实战:网络变压器在POE应用中的AF/AT/BF/BT详解与电路设计指南
1. 网络变压器在POE系统中的核心作用 第一次接触POE供电系统时,我对着电路板上那个带铁壳的方形元件研究了半天——这就是网络变压器。它看起来平平无奇,却是整个POE系统的"心脏"。简单来说,网络变压器在POE系统中要同时干两件事&a…...
