Big o 这个函数是O(n)吗,即使它有3个for循环?

Big o 这个函数是O(n)吗,即使它有3个for循环?,big-o,Big O,我发现了一个函数,在给定一些炸弹和雷区大小的情况下实现了一个扫雷舰雷区。我想用大O表示法计算函数的时间复杂度 功能扫雷车获取一个名为炸弹的数组,以及num\u rows和num\u cols的行数和列数,并返回雷区: def mine_sweeper(bombs, num_rows, num_cols): field = [[0 for i in range(num_cols)] for j in range(num_rows)] for bomb in bombs:

我发现了一个函数,在给定一些炸弹和雷区大小的情况下实现了一个扫雷舰雷区。我想用大O表示法计算函数的时间复杂度

功能
扫雷车
获取一个名为
炸弹
的数组,以及
num\u rows
num\u cols
的行数和列数,并返回雷区:

def mine_sweeper(bombs, num_rows, num_cols):
    field = [[0 for i in range(num_cols)] for j in range(num_rows)]
    for bomb in bombs:
        (row_i, col_i) = bomb
        field[row_i][col_i] = -1
        for i in range(row_i - 1, row_i + 2):
            for j in range(col_i - 1, col_i + 2):
                if (0 <= i < num_rows and 0 <= j < num_cols
                        and field[i][j] != -1):
                    field[i][j] += 1
    return field

# For example
# mine_sweeper([[0, 2], [2, 0]], 3, 3) should return:
# [[0, 1, -1],
# [1, 2, 1],
# [-1, 1, 0]]
def扫雷机(炸弹、行数、列数):
字段=[[0表示范围内的i(num_cols)]表示范围内的j(num_行)]
对于炸弹中的炸弹:
(第一排,第一列)=炸弹
字段[行i][列i]=-1
对于范围内的i(第i-1行,第i+2行):
对于范围内的j(列i-1,列i+2):

如果(0如果我们假设每个语句(包括对列表项的访问)在恒定时间内确定性地运行,那么每个内部for循环将有大约3倍的恒定因子。取它们的乘积,得到9n;然而,由于大O表示法只关心限制行为,它相当于O(n),因此您是对的

这个函数是O(n)吗,其中n是炸弹的数量?

是的,确实如此,但事实并非如此:-)

这是因为两个内部循环与列数或行数完全无关。它们只是在
上一行/当前行/下一行
行/列
上进行迭代,有效地使它们的时间保持不变

实际上,您已经了解了复杂性分析的一个方面,这是大多数初学者所忽略的:

什么是
n

这里有很多可能性:炸弹、行、列、单元,或者这些的一些产物

然而,炸弹的使用绝对是不正确的,因为这本身就受到电池数量的限制。假设正常的扫雷艇规则是每个单元最多有一枚炸弹,那么限制因素就是单元的数量,所以这就是你应该使用的
n

因此,炸弹处理回路(其恒定时间主体,见上文)和现场初始化:

field = [[0 for i in range(num_cols)] for j in range(num_rows)]
最终受到细胞计数的限制

而且,由于两个连续的(非嵌套的)
O(n)
操作仍然是
O(n)
,这就是您的复杂性


不过,我想提出的一点与现实世界的影响有关。复杂性分析非常有助于了解输入变大时会发生什么。这意味着像排序这样的事情,可能需要对20个项目或1000亿个项目进行排序


在像扫雷舰这样的游戏中,它并没有那么有用,因为你很可能被限制在3840x2160这样的分辨率上。考虑到20x20的微小单元,即192x108或约20000个单元。这是你的计算机在一眨眼之前,甚至在你的自主神经系统发出的信号到达你的眼皮开始这一过程之前,都要完成的事情:-)

不。如果
n
是炸弹的数量,那么
n
不能超过细胞的数量。当
n
等于单元数时所做的工作量是算法不能超过的固定限制。因此,如果我们假设细胞的数量是恒定的,它是O(1)

如果我们假设细胞的数量是可变的,它不是O(n)

所以没有任何假设可以得出结论,这是O(n)。(除此之外,您将此命名为“扫雷者”,尽管它不是一个给定单元格中最多只能有一枚地雷的经典扫雷游戏/算法/问题。)

让我们调用R表示行数,C表示列数。在传统的扫雷艇中,炸弹的数量是电池数量的一部分,也就是说,装有炸弹的电池的数量是恒定的。在这种情况下:

  • 炸弹的最大数量是R*C
  • 外部循环迭代O(R*C)次
  • 下一个循环迭代O(R)次
  • 下一个循环迭代O(C)次
  • 所以整个算法是O(R^2*C^2)

  • 如果N是电池的数量,如果一个电池含有地雷的概率是常数,那么它就是O(N^2)。相反,如果炸弹的数量是恒定的,那么它就是O(N),其中N是单元的数量。

    因为函数定义了
    字段=[[0代表范围内的i(num\u cols)]代表范围内的j(num\u rows)]

    在战场上,炸弹的数量最多与单元的数量相同,其复杂性是
    O(num\u cols*num\u rows)

    只是为了初始化数组


    如果我们分析函数的其余部分,我们有
    bombs
    ,其中
    bombs.size即使它是O(n),其中
    n
    是炸弹的数量,但它不是O(n),其中
    n
    是单元的数量。由于炸弹的数量不能超过电池的数量,所以让
    n
    成为炸弹的数量是没有意义的。Big-O表示法是指当某物在没有边界的情况下增加,炸弹的数量在没有边界的情况下不能增加时会发生什么。请澄清2D数组
    炸弹
    的内容好吗?它如何代表竞争环境?这是什么编程语言?这个例子有用吗<代码>炸弹
    是一个数组,其格式为<代码>[[行,列],…]
    ,输出数组是雷区在给定大小和给定数量炸弹的情况下的样子。它确实是:)因为这只是限制行为,他错了。炸弹的数量不能超过牢房的数量。所以有一个恒定的极限,它不能超过。因此,如果单元数不变,则为O(1),如果单元数可变,则为O(n)。@DavidSchwartz在理想条件下,您是正确的,但如果我们只考虑OP中提到的算法,则其时间将与
    中的项目数成正比,是否有重复。假设一个单元可以有多个炸弹。虽然可能,但考虑到他将函数命名为“mine_-swee”,这是一个非常不可能的假设
    
     if (0 <= i < num_rows and 0 <= j < num_cols and field[i][j] != -1):
                        field[i][j] += 1