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

Algorithm 这个BFS算法的时间复杂度是多少?,algorithm,math,time-complexity,breadth-first-search,Algorithm,Math,Time Complexity,Breadth First Search,对于这个问题,我用下面的算法解决了它。问题是 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,…sqrtn]从目

对于这个问题,我用下面的算法解决了它。问题是

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,…sqrtn]从目标数字变为0,然后对获得的每个数字做相同的工作。我很难理解这个算法的时间复杂度,因为每个级别的分支都是sqrtn次,但有些分支注定要提前结束

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

如果你想一想你在做什么,你可以想象你在一个有n+1个节点的图上进行广度优先搜索,所有的自然数都在0和n之间,包括一些边m,我们将在后面确定。你的图基本上被表示为邻接表,因为在每一点上,你都会迭代所有小于或等于你的数的出射边方块,一旦你考虑一个太大的方块,就停止。因此,运行时将启用+m,我们现在要做的就是计算出m是什么

在计算所有平方根(包括n)的过程中还有另一个成本,但这需要1/2的时间,这主要是由On项决定的

如果你仔细想想,每个数字k的输出边的数量将由小于或等于k的完美正方形的数量给出。该值等于⌊√K⌋ 检查以下几个示例-它很有效!。这意味着总边数的上限为

√0 + √1 + √2 + ... + √n

我们可以证明这个总和是Θn3/2。首先,我们将这个总和的上限设为3/2,我们可以通过注意

√0 + √1 + √2 + ... + √n

≤ √n+√n+√ n+…+√n+1次

=n+1√n

=3/2

要将其下限设为Ωn3/2,请注意

√0 + √1 + √2 + ... + √ n

≥ √n/2+√n/2+1+…+√n放弃前一半条款

≥ √n/2+√n/2+…+√n/2

=n/2√n/2

=Ωn3/2

因此,总体而言,边的数量为3/2,因此使用宽度优先搜索的常规分析,我们可以看到运行时间为3/2

这个界限可能并不严格,因为它假设您访问每个节点和每个边缘,而这是不会发生的。然而,我不知道如何把事情做得更紧

需要注意的是,这将是一个使用*搜索而不是广度优先搜索的好地方,因为你可以很容易地想出一些启发式方法来低估剩余的总距离,比如,取这个数字,除以小于它的最大完美平方。这将导致搜索集中在非常有希望的路径上,这些路径在不太好的路径之前快速跳转到0,比如说,总是采取大小为1的步骤


希望这有帮助

如果你想一想你在做什么,你可以想象你在一个有n+1个节点的图上进行广度优先搜索,所有的自然数都在0和n之间,包括0和n,还有一些边m,我们将在后面确定。你的图基本上被表示为邻接表,因为在每一点上,你都会迭代所有小于或等于你的数的出射边方块,一旦你考虑一个太大的方块,就停止。因此,运行时将启用+m,我们现在要做的就是计算出m是什么

在计算所有平方根(包括n)的过程中还有另一个成本,但这需要1/2的时间,这主要是由On项决定的

如果你仔细想想,每个数字k的输出边的数量将由小于或等于k的完美正方形的数量给出。该值等于⌊√K⌋ 检查以下几个示例-它很有效!。这意味着总边数的上限为

√0 + √1 + √2 + ... + √n

我们可以证明这个总和是Θn3/2。首先,我们将这个总和的上限设为3/2,我们可以通过注意

√0 + √1 + √2 + ... + √n

≤ √n+√n+√ n+…+√n+1次

=n+1√n

=3/2

要将其下限设为Ωn3/2,请注意

√0 + √1 + √2 + ... + √ n

≥ √n/2+√n/2+1+…+√n放弃前一半条款

≥ √n/2+√n/2+…+√n/2

=n/2√n/2

=Ωn3/2

因此,总体而言,边的数量为3/2,因此使用宽度优先搜索的常规分析,我们可以看到运行时间为3/2

这个界限可能并不严格,因为它假设您访问每个节点和每个边缘,而这是不会发生的。然而,我不知道如何把事情做得更紧

需要注意的是,这将是一个使用*搜索而不是广度优先搜索的好地方,因为你可以很容易地想出一些启发式方法来低估剩余的总距离,比如,取这个数字,除以小于它的最大完美平方。那个 将导致搜索集中在非常有希望的路径上,这些路径在不太好的路径之前快速跳转到0,比如说,总是采取大小为1的步骤

希望这有帮助

一些观察结果:

n以内的方块数为√n到最接近的整数 在while循环的第一次迭代之后,tempQueue将具有√n个条目 tempQueue的条目不能超过n个,因为所有这些值都是正数、小于n且唯一的。 每一个自然数都可以写成整数。这意味着BFS算法的while循环最多迭代4次。如果return语句在前3次迭代中的任何一次都没有执行,则保证在第4次迭代中执行。 除了方块的初始化外,每一条语句都以恒定的时间运行,甚至调用.add也是如此。 正方形的初始化有一个列表理解循环√n次迭代,范围以恒定时间运行,因此初始化的时间复杂度为O√N 现在,我们可以为if node square==0语句或最内层循环体中的任何其他语句的执行次数设置上限:

一,⋅√n+√N⋅√n+n⋅√n+n⋅√n

这4项中的每一项都对应于while循环的一次迭代。每个乘积的左因子对应于特定迭代中队列的最大大小,右因子对应于始终相同的正方形大小。这简化为:

√n+n+2n3/2

就时间复杂性而言,这是:

ON 3⁄2

这是时间复杂度最差的情况。当while循环只需要迭代两次时,它是打开的;当n是正方形时,它只需要迭代一次,它是O√n、 一些观察结果:

n以内的方块数为√n到最接近的整数 在while循环的第一次迭代之后,tempQueue将具有√n个条目 tempQueue的条目不能超过n个,因为所有这些值都是正数、小于n且唯一的。 每一个自然数都可以写成整数。这意味着BFS算法的while循环最多迭代4次。如果return语句在前3次迭代中的任何一次都没有执行,则保证在第4次迭代中执行。 除了方块的初始化外,每一条语句都以恒定的时间运行,甚至调用.add也是如此。 正方形的初始化有一个列表理解循环√n次迭代,范围以恒定时间运行,因此初始化的时间复杂度为O√N 现在,我们可以为if node square==0语句或最内层循环体中的任何其他语句的执行次数设置上限:

一,⋅√n+√N⋅√n+n⋅√n+n⋅√n

这4项中的每一项都对应于while循环的一次迭代。每个乘积的左因子对应于特定迭代中队列的最大大小,右因子对应于始终相同的正方形大小。这简化为:

√n+n+2n3/2

就时间复杂性而言,这是:

ON 3⁄2

这是时间复杂度最差的情况。当while循环只需要迭代两次时,它是打开的;当n是正方形时,它只需要迭代一次,它是O√n