C++ 什么';这个数独算法的时间复杂度是多少?
数独求解器C++ 什么';这个数独算法的时间复杂度是多少?,c++,algorithm,big-o,depth-first-search,sudoku,C++,Algorithm,Big O,Depth First Search,Sudoku,数独求解器编写一个程序,通过填充空单元格来解决数独难题。 空单元格由字符“.”表示。您可以假定 只有一个唯一的解决方案 我个人认为,时间复杂度=O((n^2)!),n是董事会的行数(col)。 C++ 类解决方案{ 公众: 数独(矢量和棋盘){ //输入验证。 如果(board.size()==0|| board.size()!=板[0]。大小()|| board.size()%3!=0)返回; 助理董事局; } bool辅助工具(向量和板){ //基本情况。 // ... ... 用于(int
编写一个程序,通过填充空单元格来解决数独难题。
空单元格由字符“.”表示。
您可以假定 只有一个唯一的解决方案
我个人认为,
时间复杂度=O((n^2)!),n是董事会的行数(col)。
C++
类解决方案{
公众:
数独(矢量和棋盘){
//输入验证。
如果(board.size()==0||
board.size()!=板[0]。大小()||
board.size()%3!=0)返回;
助理董事局;
}
bool辅助工具(向量和板){
//基本情况。
// ... ...
用于(int row=0;row 对于(char num='1';num您假设O((n^2)!)的原因是什么?因为这是一个带有回溯的经典递归,在没有深入分析问题的情况下,我会认为它是O(n^n)。尝试创建一个每次递归调用函数时递增的计数器。然后查看算法结束时它是否接近387 420 489(我的猜测)或579 712 600 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
如果你想要一个更复杂的解释,我很乐意给你一个
编辑:
在考虑详细的解释时,我注意到我对数字的理解是错误的,它们实际上应该更高一些
许多递归搜索可以建模为一棵树。在Sodoku中,每次尝试一个新字段时,您都有9种可能性。最多,您必须将解决方案放入所有81个字段中。此时,它可以帮助绘制它,以便看到生成的搜索空间是一棵树,深度为81,每个字段的每个节点的分支因子为9层,每个叶都是可能的解决方案。给定这些数字,搜索空间为9^81
由于您在尝试81次后没有检查解决方案是否正确,但每次尝试后,实际的搜索空间要小得多。我真的不知道如何将其转化为数字,作为粗略估计,每次设置n次尝试时,分支因子可能会变小1。但是,如果给定任何具有k个预设数字的Sodoku,您可以100%确定s是的,您最多需要n^(n²-k)次尝试
那个有意义吗?只是为了好玩,我提出了这个解决方案:定义F为(i80)F;printf(%d%c,s[I++),I%9>7?10:32)有意义吗?/p>只是为了好玩,我提出了这个解决方案:我提出了这个解决方案:定义F为(i80)F;printff(%d%c,s[I+c,s[I++,s[I%c,s[s[I++9>7.9>7?7?10?10:7?10:7?10:7?10:7?10:30:32)3)3)32)还有其他;如果(7.10:32)还有其他如果如果(+++s[9[10.10.10.10.10.10.10.10.10.10.10.10.10.10.10.10.10(10.10.10.10.10.10.10.10(10.10.10:32)是谢谢阿恩,你是对的,它不应该是O((n^2)!),但我仍然不明白为什么它是O(n^n)(n是行数或列数)。如果您愿意提供解释,那就太好了。非常感谢您。我相信如果(board[row][col]!=”)继续,在isValid()的每个循环中再次增加计数器将是最合适的。(这有效地去除了O(kX)中的常数因子k,其中X是实际运行时的非常数部分,但仍然对每个循环迭代进行计数。)关于代码,应该在尝试一个数字后立即检查电路板是否有效。如果解决方案无效,这将阻止算法在递归调用后尝试9次。我还认为没有必要再次用“.”清除字段,仅在返回“false”之前的回滚时进行。
class Solution {
public:
void solveSudoku(vector<vector<char> > &board) {
// Input validation.
if (board.size() == 0 ||
board.size() != board[0].size() ||
board.size() % 3 != 0) return;
helper(board);
}
bool helper(vector<vector<char>>& board) {
// Base case.
// ... ...
for (int row = 0; row < board.size(); row ++) {
for (int col = 0; col < board[0].size(); col ++) {
if (board[row][col] != '.') continue;
for (char num = '1'; num <= '9'; num ++) {
if (isValid(board, num, row, col)) {
// Have a try.
board[row][col] = num;
// Do recursion.
if (helper(board)) return true;;
// Roll back.
board[row][col] = '.';
}
}
// Can not find a suitable number[1-9].
return false;
}
}
return true;
}
bool isValid(const vector<vector<char>>& board, char num, int row, int col) {
// Check row.
for (int tmp_col = 0; tmp_col < board[0].size(); tmp_col ++) {
if (board[row][tmp_col] == num) return false;
}
// Check col.
for (int tmp_row = 0; tmp_row < board.size(); tmp_row ++) {
if (board[tmp_row][col] == num) return false;
}
// Check sub square.
int start_row = (row / 3) * 3;
int start_col = (col / 3) * 3;
for (int row = start_row; row < start_row + 3; row ++) {
for (int col = start_col; col < start_col + 3; col ++) {
if (board[row][col] == num) return false;
}
}
return true;
}
};