您好,我一直在研究https://leetcode.com/problems/2-keys-keyboard/submissions/,并遇到了这个动态编程问题。
您在空白页上以'A'开头,完成后会得到数字n
,在页面上应该用n
乘以'A'。要注意的是,您只能进行2次操作复制(并且您只能复制页面上当前的A总数)并粘贴->找到在页面上获得n
'A'的最小操作数
我写了下面的算法来解决这个问题,但是我在分析它的时间复杂度上却很费力。
代码如下:
def minSteps(self, n: int) -> int:
DP = [0] + [0] + [i for i in range(2, n+1)]
for d in range(2, n+1):
for i in range(d*2, n+1, d):
DP[i] = min(DP[i], DP[d] + i//d )
return DP[n]
所以我的直觉说,此算法在O(n^2)
和O(nlogn)
之间,因为在第二个循环中我们比O(n)
更快,但是由于步长{{1} }不会在每次迭代之间加倍,但在第二个循环中仍然是d
...
我不确定该如何分析,欢迎任何帮助。
答案 0 :(得分:2)
让我们看一下外部循环-它执行了O(N)
次。
每个内部循环都在执行O(N / d)
操作,因为索引的跳转位于d
中。
因此计算为:
N / 1 + N / 2 + N / 3 + ... + 1
请注意,这笔款项中有N
个项目。
我们可以取出N
:
N * (1 / 1 + 1 / 2 + 1 / 3 + ... + 1 / N)
大约是:
N * ln N
(直觉是,通过集成函数1 / N
,您会得到ln
)
因此,总体复杂度为O(N log N)
答案 1 :(得分:0)
您的解决方案是O(nlogn)
。这是一个更有效的解决方案:
def minSteps(self, n: int) -> int:
ans = 0
d = 2
while n >= d * d:
while n % d == 0:
ans += d
n //= d
d += 1
if n != 1:
ans += n
return ans
此解决方案基于LeetCode上发布的解决方案,但速度更快。时间复杂度为O(sqrt(p))
,其中p
是n
的最大素数。