Algorithm 回溯经典n皇后的时间复杂度分析
我一直在读一些解决经典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])
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项也会加起来。