【发布时间】:2015-11-18 13:12:06
【问题描述】:
我一直在阅读一些解决经典 n-queens 问题的代码。只是找到一种解决方案(不是全部解决方案或计算解决方案的数量)。您可以在geeksforgeeks website 上找到完整的代码,总结如下。 问题是,这段代码的时间复杂度是多少,真的?
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;
}
如果你回顾一下 cmets 的历史,有人会说它是 O(n!),甚至是指数级的。但我认为它们都不正确。
例如,对于O(n!) 的声明,一个给T(n)= n*(T(n-1) + O(n)) 导致O(n!)。
为什么我认为这是错误的(不是O(n!))?
1.问题是,solveNQUtil 中的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))。 是这样吗?
谁能指出这是否正确并给出适当的推理?
【问题讨论】:
标签: algorithm big-o backtracking n-queens