Algorithm 回溯经典n皇后的时间复杂度分析

Algorithm 回溯经典n皇后的时间复杂度分析,algorithm,big-o,backtracking,n-queens,Algorithm,Big O,Backtracking,N Queens,我一直在读一些解决经典n皇后问题的代码。这只是找到一个解决方案(不是全部,也不是全部)。您可以在上找到完整的代码,总结如下问题是,这段代码的时间复杂度是多少 bool isSafe(int board[N][N], int row, int col) { int i, j; /* Check this row on left side */ for (i = 0; i < col; i++) if (board[row][i])

我一直在读一些解决经典n皇后问题的代码。这只是找到一个解决方案(不是全部,也不是全部)。您可以在上找到完整的代码,总结如下问题是,这段代码的时间复杂度是多少

bool isSafe(int board[N][N], int row, int col)
{
    int i, j;

    /* Check this row on left side */
    for (i = 0; i < col; i++)
        if (board[row][i])
            return false;

    /* Check upper diagonal on left side */
    for (i=row, j=col; i>=0 && j>=0; i--, j--)
        if (board[i][j])
            return false;

    /* Check lower diagonal on left side */
    for (i=row, j=col; j>=0 && i<N; i++, j--)
        if (board[i][j])
            return false;

    return true;
}

/* A recursive utility function to solve N
   Queen problem */
bool solveNQUtil(int board[N][N], int col)
{
    /* base case: If all queens are placed
      then return true */
    if (col >= N)
        return true;

    /* Consider this column and try placing
       this queen in all rows one by one */
    for (int i = 0; i < N; i++)
    {
        /* Check if queen can be placed on
          board[i][col] */
        if ( isSafe(board, i, col) )
        {
            /* Place this queen in board[i][col] */
            board[i][col] = 1;

            /* recur to place rest of the queens */
            if ( solveNQUtil(board, col + 1) )
                return true;

            /* If placing queen in board[i][col]
               doesn't lead to a solution, then
               remove queen from board[i][col] */
            board[i][col] = 0; // BACKTRACK
        }
    }

     /* If queen can not be place in any row in
        this colum col  then return false */
    return false;
}

/* This function solves the N Queen problem using
   Backtracking. It mainly uses solveNQUtil() to
   solve the problem. It returns false if queens
   cannot be placed, otherwise return true and
   prints placement of queens in the form of 1s.
   Please note that there may be more than one
   solutions, this function prints one  of the
   feasible solutions.*/
bool solveNQ()
{
    int board[N][N] = { {0, 0, 0, 0},
        {0, 0, 0, 0},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    };

    if ( solveNQUtil(board, 0) == false )
    {
      printf("Solution does not exist");
      return false;
    }

    printSolution(board);
    return true;
}
bool-isSafe(内部板[N][N],内部行,内部列)
{
int i,j;
/*检查左侧的这一行*/
对于(i=0;i=0&&j>=0;i--,j--)
如果(董事会[i][j])
返回false;
/*检查左侧的下对角线*/
对于(i=row,j=col;j>=0&&i=N)
返回true;
*考虑此栏并尝试放置
这是一个一个排的女王*/
对于(int i=0;i
如果你浏览了评论的历史,有人说它是
O(n!)
,甚至是指数型的。但我认为他们两个都不对

例如,对于
O(n!)
的索赔,有人给出了
T(n)=n*(T(n-1)+O(n))
,这导致了
O(n!)

为什么我认为这是错误的(不是
O(n!)
)?
1.问题是,
solvenktil
中的
for
循环总是运行
N次。它不会随着问题范围的减小而减小
n
。因此,上述公式中的乘数
n
不正确。应将其替换为固定编号
N

2.
isSafe
中的
col
在递归树下增加,这意味着
isSafe
中的
for
循环有越来越多的迭代。迭代次数是
N-N

所以基本上,递归应该是
T(n)=n*(T(n-1)+O(n-n))
(n是固定的)。不确定如何解决这个问题,但它至少应该是
O(N^N)
有什么想法吗?

递归树方法 如果使用递归树,则有
O(n^n)
到叶子的不同路径,每个路径都采用
O(1+2+…n)
操作进行冲突检查。所以总时间应该是
O(n^(n+2))
是这样吗?


有人能指出这是否正确并给出适当的理由吗?

这是一个很好的观察结果。让我思考和模拟很多步骤

通过只看代码并尝试推导复杂度,您实际上是对的,它应该是O(n^n)

但问题是,尽管
solvenktil
中的内部循环运行了N次,但递归函数
solvenktil
没有被调用N次。在最坏的情况下,它将被调用
n-1次。因为前面的每一列都有一个皇后,所以在迭代这些列时,其中一行将从进一步考虑中删除。因此,不要重复

T(n)= N *(T(n-1))
这确实是间接的

T(n)= n *(T(n-1))

谢谢没错。再进行一次递归调用时,至少还有一次
isSafe
应返回false。因此
迭代的#of
每次重复调用至少减少1次。对于
isSafe
中的开销,由于
col
行已经被填充,因此对于(i=0;i迭代次数最多为
min(col,N-col+1)
。所以这个循环实际上是
T(n)=n*(T(n-1)+O(n))
。嘿,我仔细考虑了一下。复发应该是
T(n)=n*T(n-1)+n*n
,这导致
O((n+1)!)
而不是
O(n!)
。这是因为尽管递归调用的数量减少,但
solvenktil()
循环迭代的
数量保持不变(
N
)。你觉得怎么样?告诉我,这个循环是如何在O(n+1!)中结束的。试着举一些简单的例子,让我知道你发现了什么。这是一个很好的复杂性分析练习:)。虽然你是对的,N*N项也会加起来。