[英]How can I improve the runtime of Python implementation of cycle detection in Course Schedule problem?
我的目標是提高我的 Python 代碼的速度,該代碼已在leetcode 問題 Course Schedule中成功接受。
我知道該算法,但即使我使用 O(1) 數據結構,我的運行時間仍然很差:大約 200 毫秒。
我的代碼使用字典和集合:
from collections import defaultdict
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
course_list = []
pre_req_mapping = defaultdict(list)
visited = set()
stack = set()
def dfs(course):
if course in stack:
return False
stack.add(course)
visited.add(course)
for neighbor in pre_req_mapping.get(course, []):
if neighbor in visited:
no_cycle = dfs(neighbor)
if not no_cycle:
return False
stack.remove(course)
return True
# for course in range(numCourses):
# course_list.append(course)
for pair in prerequisites:
pre_req_mapping[pair[1]].append(pair[0])
for course in range(numCourses):
if course in visited:
continue
no_cycle = dfs(course)
if not no_cycle:
return False
return True
我還能做些什么來提高速度?
您多次為給定course
調用dfs()
。 但它的返回值不會改變。 所以我們有機會記住它。 改變你的算法方法(這里是動態編程)以獲得巨大的勝利。 這是空間與時間的權衡。 編輯:嗯,你已經用visited
記住了大部分計算,所以lru_cache
主要會提高清晰度而不是運行時間。 這只是緩存結果的一種熟悉的習慣用法。
添加#
注釋引用您實現的算法的參考會很有幫助。
這是一個非常好的表達式,默認為: pre_req_mapping.get(course, [])
如果你使用timeit ,你可能會發現為空元組()
生成的字節碼比為空列表[]
,因為它涉及較少的分配。 好的,一些風格尼特遵循,與運行時無關。
順便說一句,youAreMixing CamelCase 和_snake_case。 PEP-8 要求你堅持使用 snake_case。
這是標識符名稱的一個很好的選擇:
for pair in prerequisites:
但不是神秘的[0]
, [1]
解引用,而是更容易閱讀元組解包:
for course, prereq in prerequisites:
if not no_cycle:
是笨拙的。 考慮反轉 dfs 的返回值的含義,或將賦值改寫為:
cycle = not dfs(course)
我認為您做得很好,但是由於 Python 是一種解釋性語言,與 C/C++ 和 Java 等編譯語言相比,運行時間很慢是正常的,尤其是對於大輸入。
例如,嘗試用 C/C++ 編寫相同的代碼並比較它們之間的速度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.