LeetCod问题链接: https://leetcode.com/problems/open-the-lock/(第screenshot页)
下面是代码#1从源代码和目标代码执行bfs:
from collections import deque
class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
deadend = set(deadends)
if target in deadend or '0000' in deadend:
return -1
if target == '0000':
return 0
def getNextCombi(combi: str) -> List[str]:
res = []
for i in range(4):
nextCombi1 = combi[:i] + str((int(combi[i:i + 1]) + 1) % 10) + combi[i + 1:]
nextCombi2 = combi[:i] + str((int(combi[i:i + 1]) - 1) % 10) + combi[i + 1:]
if nextCombi1 not in deadend:
res.append(nextCombi1)
if nextCombi2 not in deadend:
res.append(nextCombi2)
return res
sourceQueue = deque(['0000'])
targetQueue = deque([target])
sourceSeen = {'0000': 0}
targetSeen = {target: 0}
while len(sourceQueue) != 0 and len(targetQueue) != 0:
sourceCombi = sourceQueue.popleft()
targetCombi = targetQueue.popleft()
for nextCombi in getNextCombi(sourceCombi):
if nextCombi not in sourceSeen:
sourceSeen[nextCombi] = sourceSeen[sourceCombi] + 1
sourceQueue.append(nextCombi)
if nextCombi in targetSeen:
return sourceSeen[nextCombi] + targetSeen[nextCombi]
for nextCombi in getNextCombi(targetCombi):
if nextCombi not in targetSeen:
targetSeen[nextCombi] = targetSeen[targetCombi] + 1
targetQueue.append(nextCombi)
if nextCombi in sourceSeen:
return sourceSeen[nextCombi] + targetSeen[nextCombi]
return -1
下面是代码#2从源代码执行bfs:
from collections import deque
class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
deadend = set(deadends)
if target in deadend or '0000' in deadend:
return -1
if target == '0000':
return 0
def getNextCombi(combi: str) -> List[str]:
res = []
for i in range(4):
nextCombi1 = combi[:i] + str((int(combi[i:i + 1]) + 1) % 10) + combi[i + 1:]
nextCombi2 = combi[:i] + str((int(combi[i:i + 1]) - 1) % 10) + combi[i + 1:]
if nextCombi1 not in deadend:
res.append(nextCombi1)
if nextCombi2 not in deadend:
res.append(nextCombi2)
return res
sourceQueue = deque(['0000'])
sourceSeen = {'0000': 0}
while len(sourceQueue) != 0:
sourceCombi = sourceQueue.popleft()
for nextCombi in getNextCombi(sourceCombi):
if nextCombi not in sourceSeen:
sourceSeen[nextCombi] = sourceSeen[sourceCombi] + 1
sourceQueue.append(nextCombi)
if nextCombi == target:
return sourceSeen[nextCombi]
代码#1在LeetCode上给出了大约120毫秒的速度, 代码#2在LeetCode上提供了大约640ms的速度。 我试了好几次,所以我相信算法本身有很大的不同
为什么1比2快得多? 我看不出在时间复杂性方面有什么不同。 是否仅仅因为LeetCode中使用的示例在#1上更快
我对这两种代码的分析: 我认为它们具有相同的时间复杂度O(1),因为在最坏的情况下,它会遍历所有可能的组合,即4^9。我不确定我的恒定时间复杂性,但我认为我做bfs源代码是正确的->;目标,并执行bfs源->;满足<;-目标,是一样的
下一个C++代码的测量结果(输出)为:
使用下一个测试输入(取自LeetCode示例)测量两个算法:
因此,algo1比algo2快得多,algo1只执行9304个操作码,而algo2执行155640个操作码,即16倍多的操作码。它是什么意思
opcode
-它是Python中最小的操作,与汇编程序中的指令相同,但这里的操作码是Python虚拟机中的指令。尽管某些操作码可能比其他操作码花费更长的时间,但它仍然是一个很好的定量度量(操作码的数量)这意味着即使您的两个算法都是
O(1)
,每个算法中执行的操作数仍然是非常不同的。还要记住,任何复杂性O(f(N))
实际上意味着运行时间是<= C * f(N)
,其中C
是每个算法的固定常数。例如,第一个算法可能有C = 1000
,而第二个算法可能有C = 9999
,两者都有O(1)
复杂度,但运行时间不同此外,运行的行数也非常不同。这个数字表示在执行算法时代码中已传递了多少行。它们也是很好的速度/时间测量工具
为了简单起见,您还可以只运行Python profiler(从标准库),使用以下代码行:
对于algo1:
对于algo2:
从上面两个分析器的输出中,您还可以看到,algo2比algo1执行更多的函数调用
下一个C++代码可以使用任何编译器,如MsVC/CLAN/GCC在Windows /Linux/MACOS上编译。在我的例子中,我使用64位Windows 10上的CLang进行编译。我使用了next命令行来编译它
C:\bin\llvm\bin\clang++.exe -g -m64 -O3 -std=c++20 -Ic:/bin/python39/include main.cpp c:/bin/python39/libs/python39.lib
,这里您必须提供正确的CLang和Python安装路径。如果您想安装与我相同的CLang,请转到LLVM releases并下载LLVM-11.1.0-win64.exe这里是C++代码本身:
Try it online!
相关问题 更多 >
编程相关推荐