对于问题https://leetcode.com/problems/perfect-squares/,我已使用以下算法解决了该问题。问题是
Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.
Example 1:
Input: n = 12
Output: 3
Explanation: 12 = 4 + 4 + 4.
它的作用基本上是尝试通过减去每个可能的数字(从[1,4、9,.. sqrt(n)])从目标数字变为0,然后对获得的每个数字执行相同的工作。我很难理解这种算法的时间复杂度,因为每个级别的分支都是sqrt(n)次,但是有些分支注定要提早结束...
def numSquares(n):
squares = [i**2 for i in range(1, int(n**0.5)+1)]
step = 1
queue = {n}
while queue:
tempQueue = set()
for node in queue:
for square in squares:
if node-square == 0:
return step
if node < square:
break
tempQueue.add(node-square)
queue = tempQueue
step += 1
答案 0 :(得分:1)
如果您考虑自己在做什么,可以想象您正在对具有n + 1个节点(所有自然数在0到n之间,包括0和n,包括零)的图进行广度优先搜索。边m,我们稍后会确定。您的图实质上表示为邻接表,因为在每个点上,您都在所有出站边(小于或等于您的数字的正方形)上进行迭代,并在考虑到太大的正方形后立即停止。结果,运行时将为O(n + m),现在我们要做的就是算出m是什么。
(在计算直到n并包括n的所有平方根时,还有另一个成本,但这需要花费时间O(n 1/2 ),该时间由O(n)项决定。 )
如果考虑一下,从每个数字k传出的边的数量将由小于或等于k的完全平方的数量给出。该值等于⌊√k⌋(请查看一些示例-可行!)。这意味着边的总数上限为
√0+√1+√2+ ... +√n
我们可以证明这个和为Θ(n 3/2 )。首先,我们将这个总和的上限设为O(n 3/2 ),我们可以这样做
√0+√1+√2+ ... +√n
≤√n+√n+√n + ... +√n(n + 1)次
=(n + 1)√n
= O(n 3/2 )。
要将其下限限制为Ω(n 3/2 ),请注意
√0+√1+√2+ ... +√n
≥√(n / 2)+√(n / 2 +1)+ ... +√(n)*(删除术语的前半部分)
≥√(n / 2)+√(n / 2)+ ... +√(n / 2)
=(n / 2)√(n / 2)
=Ω(n 3/2 )。
因此,总体而言,边的数量为Θ(n 3/2 ),因此使用广度优先搜索的常规分析,我们可以看到运行时间将为O(n 3/2 )。
这个界限可能并不紧密,因为这假设您访问了每个节点和每个边缘,而这不会发生。但是,我不确定如何在此基础上进一步加强工作。
请注意-这是使用A *搜索而不是广度优先搜索的绝佳位置,因为您可以很容易地提出启发式算法来低估剩余的总距离(例如,将数字除以最大的完美平方除以它)。这将导致搜索集中在极有前途的路径上,这些路径会在劣等路径之前迅速趋向于0,例如,总是采用1的步长。
希望这会有所帮助!
答案 1 :(得分:1)
一些观察:
while
循环的第一次迭代之后,tempQueue
将具有√n个条目tempQueue
的条目永远不能超过 n 个,因为所有这些值都是正数,小于 n 并且是唯一的。while
循环最多可迭代4次。如果return
语句在前3次迭代中均未执行,则可以保证在第4 次执行。squares
的初始化除外)都恒定运行,甚至是对.add()
的调用。squares
的初始化具有一个列表理解循环,该循环具有√n个迭代,并且range
在恒定的时间内运行,因此初始化的时间复杂度为 O(√n)。现在,我们可以为if node-square == 0
语句(或最里面的循环体内的任何其他语句)的执行次数设置一个上限:
1⋅√n+√n⋅√n+n⋅√n+n⋅√n
4个术语中的每一个都对应于while
循环的迭代。每个乘积的左因子对应于该特定迭代中queue
的最大大小,而右因子则对应于squares
的大小(始终相同)。简化为:
√n+ n + 2n 3⁄2
就时间复杂度而言,这是:
O(n 3⁄2 )
这是最坏情况下的时间复杂度。当while
循环只需要迭代两次时,它就是 O(n),而当只有一次时(当 n 是一个正方形时),它是< em> O(√n)。