Python算法題集_圖論(課程表)

?Python算法題集_課程表

  • 題207:課程表
  • 1. 示例說明
  • 2. 題目解析
    • - 題意分解
    • - 優化思路
    • - 測量工具
  • 3. 代碼展開
    • 1) 標準求解【循環+遞歸+全算】
    • 2) 改進版一【循環+遞歸+緩存】
    • 3) 改進版二【循環+遞歸+緩存+反向計算】
    • 4) 改進版三【迭代剝離+計數器檢測】
  • 4. 最優算法
  • 5. 相關資源

本文為Python算法題集之一的代碼示例

題207:課程表

1. 示例說明

你這個學期必須選修 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 。這是不可能的。

提示:

  • 1 <= numCourses <= 2000
  • 0 <= prerequisites.length <= 5000
  • prerequisites[i].length == 2
  • 0 <= ai, bi < numCourses
  • prerequisites[i] 中的所有課程對 互不相同

2. 題目解析

- 題意分解

  1. 本題是計算是否會出現無法學習的課程,這種課程的特點是前置課程出現環路,比如A課程的前置課程B的前置課程為A課程
  2. 本題必須進行課程遍歷,每個課程都需要檢測是否出現環路
  3. 基本的設計思路是循環+遞歸,循環遍歷課程,遞歸檢測環路

- 優化思路

  1. 通常優化:減少循環層次

  2. 通常優化:增加分支,減少計算集

  3. 通常優化:采用內置算法來提升計算速度

  4. 分析題目特點,分析最優解

    1. 如果一個課程已經檢測沒有出現環路,則前置課程檢測到此課程就不用繼續檢測下去,減少計算量

    2. 可以研究迭代法實現科目檢測


- 測量工具

  • 本地化測試說明: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) 改進版三【迭代剝離+計數器檢測】

特殊的迭代思路

  1. 首先必須存在沒有任何前置的科目,否則第一門科目都沒有辦法學習,直接返回False;由此可建立沒有前置科目的隊列
  2. 迭代沒有前置科目的隊列,逐步剝離此科目后置科目的計數器,如果后置科目的前置計數器清零,則作為無前置科目放入隊列
  3. 迭代完畢后檢測有效科目數量是否達標

頁面功能測試,馬馬虎虎,超過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

由于四段代碼思路一致,主要是使用的數據結構不同,因此經驗推出以下結論:

  1. 在作為隊列使用時【先進先出】,deque性能遠遠高于list
  2. 迭代器循環優于循環中進行異常檢測
  3. 下標循環和枚舉循環性能基本一致
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 ~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/697695.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/697695.shtml
英文地址,請注明出處:http://en.pswp.cn/news/697695.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring整合Junit4和Junit5

1、整合的好處 好處1&#xff1a;不需要自己創建IOC容器對象了好處2&#xff1a;任何需要的bean都可以在測試類中直接享受自動裝配 2、操作 整合junit4 ①加入依賴 <dependency><groupId>junit</groupId><artifactId>junit</artifactId><…

代碼隨想錄算法訓練營第二十三天補|669. 修剪二叉搜索樹 ● 108.將有序數組轉換為二叉搜索樹 ● 538.把二叉搜索樹轉換為累加樹

平衡樹、二叉樹、靈活應用中序遍歷&#xff08;值大小有序&#xff09; 669. 修剪二叉搜索樹 給你二叉搜索樹的根節點 root &#xff0c;同時給定最小邊界low 和最大邊界 high。通過修剪二叉搜索樹&#xff0c;使得所有節點的值在[low, high]中。修剪樹 不應該 改變保留在樹中…

Window部署SkyWalking

SkyWalking mysql的驅動依賴 選擇下載版本 v9.4 現在后解壓縮目錄結構 一、修改config目錄文件 application.yml 修改1&#xff1a; selector: ${SW_STORAGE:h2} 修改后&#xff1a; selector: ${SW_STORAGE:mysql} 修改2&#xff1a;使用mysql數據庫 mysql: properti…

通俗易懂分析:Vite和Webpack的區別

1、對項目構建的理解 先從瀏覽器出發&#xff0c; 瀏覽器是由瀏覽器內核和JS引擎組成&#xff1b;瀏覽器內核編譯解析html代碼和css代碼&#xff0c;js引擎編譯解析JavaScript代碼&#xff1b;所以從本質上&#xff0c;瀏覽器只能識別運行JavaScript、CSS、HTML代碼。 而我們在…

敏捷開發最佳實踐:領導力維度實踐案例——走動式激勵

在本節實踐案例中&#xff0c;某財險公司信息技術部高級工程師分享了組織級數字化轉型中的優秀敏捷領導力實踐&#xff0c;不僅解決了產品上市周期長、響應市場變化慢的難題&#xff0c;還打破了部門墻、提升了客戶滿意度&#xff0c;該案例將為同類企業在組織層面進行有效敏捷…

Centos7配置靜態IP詳細步驟

使用Centos虛擬機測試時一到切換網段就頭疼&#xff0c;總是會有ping不通網關、同段IP和外網的情況。下面出一個盡可能完整的排查思路和配置靜態IP的過程。以下為配置nat模式后&#xff0c;出現以上情況的網絡不通的排查思路&#xff0c;并配置win10vm8靜態IP和centos7虛機nat模…

vue3路由切換過渡動畫實現

<router-view v-slot"{ Component }"><transition name"fade" mode"out-in" appear><keep-alive><component :is"Component" /></keep-alive></transition> </router-view>/* 路由切換動畫…

SQL字符集

目標:了解字符集的概念&#xff0c;掌握MySQL數據庫存儲數據的字符集邏輯以及設置方式 字符集概念 MySQL字符集關系 解決亂碼問題 字符集設置原理 1、字符集概念 目標:了解字符集概念&#xff0c;掌握字符集存儲和讀取的實現原理 概念 字符集:charset或者character set&am…

(十二)【Jmeter】線程(Threads(Users))之setUp 線程組

簡述 操作路徑如下: 作用:在正式測試開始前執行預加載或預熱操作,為測試做準備。配置:設置預加載或預熱操作的采樣器、循環次數等參數。使用場景:確保在正式測試開始前應用程序已經達到穩定狀態,減少測試結果的偏差。優點:提供預加載或預熱操作,確保測試的準確性。缺…

Centos開機網卡自啟動失敗

問題背景 每次都要手動啟動在這里插入代碼片 解決方案: 關閉 NetworkManager 服務 systemctl disable NetworkManager systemctl stop NetworkManager重啟就會發現網卡已經可以自動啟動了

2024幻獸帕魯游戲服務器租用價格表_一年和1個月報價明細

游戲服務器租用多少錢一年&#xff1f;1個月游戲服務器費用多少&#xff1f;阿里云4核16G10M游戲服務器26元1個月、149元半年&#xff0c;騰訊云4核16G游戲服務器32元、312元一年&#xff0c;華為云26元&#xff0c;京東云主機也是26元起&#xff0c;游戲服務器配置從4核16G、4…

代碼隨想錄算法刷題訓練營day22

代碼隨想錄算法刷題訓練營day22&#xff1a;LeetCode(236)二叉樹的最近公共祖先、LeetCode(235) 二叉搜索樹的最近公共祖先、LeetCode(701)二叉搜索樹中的插入操作、LeetCode(450)刪除二叉搜索樹中的節點 LeetCode(236)二叉樹的最近公共祖先 題目 代碼 /*** Definition for…

【鴻蒙 HarmonyOS 4.0】路由router

一、介紹 頁面路由指在應用程序中實現不同頁面之間的跳轉和數據傳遞。HarmonyOS提供了Router模塊&#xff0c;通過不同的url地址&#xff0c;可以方便地進行頁面路由&#xff0c;輕松地訪問不同的頁面。 二、頁面跳轉 2.1、兩種跳轉模式&#xff1a; router.pushUrl()&…

vue2與vue3中父子組件傳參的區別

本次主要針對vue中父子組件傳參所進行講解 一、vue2和vue3父傳子區別 1.vue2的父傳子 1).在父組件子標簽中自定義一個屬性 <sonPage :子組件接收到的類名"傳輸的數據">子組件</sonPage> 2).在子組件中peops屬性中拿到自定屬性 props: {子組件接收的…

Stable Diffusion算法、結構全流程概述

Stable Diffusion能力強、功能多、插件廣&#xff0c;本文擬概述SD的全流程&#xff0c;方便梳理算法各結構的關系 1、stable diffusion訓練用ddpm, 采樣用ddim DDPM的推理采樣步長和訓練時的步長一樣&#xff0c;導致采樣步數過多&#xff0c;推理時間長。DDIM指出&#xff…

安卓游戲開發之音頻技術優劣分析

一、引言 在安卓游戲開發中&#xff0c;音頻處理技術扮演著至關重要的角色&#xff0c;它不僅能夠增強游戲的沉浸感和玩家體驗&#xff0c;還能通過聲音效果傳達關鍵的游戲信息。以下將對幾種常見的安卓游戲音頻處理技術進行優劣分析&#xff0c;并結合應用場景來闡述其特點。 …

docker鏡像打包和解壓

背景 工作記錄 打包鏡像 docker save -o 壓縮包名稱.tar 鏡像名稱:鏡像版本 例如 docker save -o app-web.tar app-web:2.0解壓鏡像 這里解壓上面打包的app-web的壓縮包 docker load<壓縮包名稱.tar docker load<app-web.tar這樣解壓下來的實際就是app-web:2.0這個鏡…

微服務-微服務API網關Spring-clould-gateway實戰

1. 需求背景 在微服務架構中&#xff0c;通常一個系統會被拆分為多個微服務&#xff0c;面對這么多微服務客戶端應該如何去調用呢&#xff1f; 如果根據每個微服務的地址發起調用&#xff0c;存在如下問題&#xff1a; 1.客戶端多次請求不同的微服務&#xff0c;會增加客戶端…

Qt 事件

1. 事件 事件是對各種應用程序需要知道的由應用程序內部或者外部產生的事情或者動作的通稱。在Qt中使用一個對象來表示一個事件&#xff0c;它繼承自QEvent類。 2. 事件和信號 事件與信號并不相同&#xff0c;比如我們使用鼠標點擊了一下界面上的按鈕&#xff0c;那么就會產生…

node 之 初步認識

思考&#xff1a;為什么JavaScript可以在瀏覽器中被執行 代執行的js代碼——JavaScript解析引擎 不同的瀏覽器使用不同的JavaScript解析引擎 Chrome 瀏覽器 》 V8 Firefox瀏覽器 》OdinMonkey(奧丁猴&#xff09; Safri瀏覽器 》JSCore IE瀏覽器 》Chakra(查克拉&#xff09; e…