我写了下面的算法来解决一个经典的回溯问题:编写一个带有n个整数数组的程序,其中A [i]表示你可以从索引i前进的最大值,并返回是否可以前进到从数组开始的最后一个索引。
换句话说,A中的第i个条目是我们可以从i前进的最大值。
例如, 如果A = [3,3,1,0,2,0,1],则可以达到最后一个索引。 如果A = [3,2,0,0,2,0,1],则不能。
我写了以下代码:
from collections import defaultdict
def array_advance(lst):
dict = defaultdict(lambda: 0)
return advance(0, lst, dict)
def advance(start_idx, lst, memo):
if start_idx >= len(lst): return False
if start_idx == len(lst) -1: return True
step_size = lst[start_idx]
for i in range(1, step_size + 1):
memo[step_size] |= advance(start_idx + step_size, lst, memo)
if memo[step_size]:
return True
return False
使用此代码,我知道只有N个函数调用。如果我们记忆,则访问每个索引并缓存函数(索引)输出。
但是,我无法理解时间复杂性。关于输入的大小,当然时间复杂度与O(N)成比例。但是,输入内容也是如此。如果每个元素是L,并且输入的大小是10L,则for循环将按O(L)缩放,运行L次(从范围(1,L + 1)开始一次),导致O( L ^ 2)。如果我回答算法问题,或者甚至试图分析时间复杂度,说时间复杂度O(N)因为时间复杂度与数组长度的关系似乎有误导性,因为它没有考虑到重要性输入。
答案 0 :(得分:1)
假设步长从不超过数组,你可以说它是O(sum(A))
,因为这是一个考虑数组元素的紧束缚。你也可以说它是O(N^2)
,因为那是最糟糕的情况。
你可以通过向后遍历数组来解决O(N)时间和O(1)空间中的问题,记录到目前为止找到的最小索引,这样你就可以到达终点。
def array_advance(a):
i = len(a) - 1
for j in range(i, -1, -1):
if j + a[j] >= i: i = j
return i == 0