这个BFS算法的时间复杂度是多少?

时间:2019-06-26 15:25:19

标签: algorithm math time-complexity breadth-first-search

对于问题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

2 个答案:

答案 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)

一些观察:

  1. 最多 n 的平方数是√n(向最接近的整数求积)
  2. while循环的第一次迭代之后,tempQueue将具有√n个条目
  3. tempQueue的条目永远不能超过 n 个,因为所有这些值都是正数,小于 n 并且是唯一的。
  4. 每个自然数都可以写为sum of four integer squares。因此,这意味着您的BFS算法的while循环最多可迭代4次。如果return语句在前3次迭代中均未执行,则可以保证在第4 次执行。
  5. 每个语句(squares的初始化除外)都恒定运行,甚至是对.add()的调用。
  6. 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)。