我有一个递归算法,它应该接收一个部分或全部为空的数独棋盘(用int[][]表示,其中0代表空白),并填充它。它对空棋盘和我输入的大多数其他棋盘都有效,但偶尔我得到一个堆栈溢出错误,指向第54行和第40行(在语句grid = copyGrid(emptyFill(grid, current + 1, cant)); )。谁能帮我改进一下?
//Creating and filling a board Recursive Methods
//Current represents the index for every cell on the board from 0 to 80 inclusive
//cant holds an array of values that the function may not place for each index
public static int[][] emptyFill(int[][] grid, int current, int[][] cant){
if(isFull(grid)){
return grid;
}
else if(getCellAt(grid, current) == 0){
for(int i = 1; i <= 9; i ++){
if(works(i, current / 9, current % 9, grid) && notInCant(cant, current, i)){
grid[current / 9][current % 9] = i;
//Line 40 below this comment
grid = copyGrid(emptyFill(grid, current + 1, cant));
return grid;
}
}
/*Backtracks backwards if no number was found by keeping track of what numbers we have tried. Should clear
up the cant list if we backtrack further than it */
for(int i = current; i < cant.length; i ++){
clearRow(cant, i);
}
addToRow(cant, current - 1, getCellAt(grid, current - 1));
setCellTo(grid, current, 0);
setCellTo(grid, current - 1, 0);
//Line 54 below this comment
grid = copyGrid(emptyFill(grid, current -1, cant));
return grid;
}
else{
grid = copyGrid(emptyFill(grid, current + 1, cant));
return grid;
}
}
问题是,当程序无法填入一个单元格时,它会 "回溯",通过清除当前和前一个单元格,更新无法放置的数字列表,然后再次调用程序。这导致该函数被调用太多次。新函数则是简单地清除单元格,当找不到合适的号码时,就退出函数。这样就可以让函数回溯,不用再调用自己,实际上又回到了之前的调用。这就是更新后的函数。
public boolean emptyFill(int[][] grid, int current){
if(isFull(grid)){
return true;
}
else if(getCellAt(grid, current) == 0){
for(int i = 1; i <= 9; i ++){
if(works(i, current / 9, current % 9, grid) && notInCant( current, i)){
grid[current / 9][current % 9] = i;
if( emptyFill(grid, current + 1)) return true;
grid[current / 9][current % 9] = 0;
}
}
return false;
}
else{
return emptyFill(grid, current + 1);
}
}