我实现了一个SuDoku回溯算法,但它一直给我StackOverflow错误。任何其他方法或算法来避免这种情况,因为我无法理解为此形成一个循环。
public boolean guess(int istart){
int i=istart, j=0; boolean found=false;
for(i=istart; i<9; i++){//find first empty cell
for(j=0; j<9; j++){
if(get(i,j)==0) {found=true; break;}
}
if(found) break;
}
boolean[] pos=pos_copy;//pos_copy is a length-9 boolean array with all elements set to true
for(int n=0; n<9; n++){//store all possible numbers in pos[]
if(get(i,n)!=0) pos[get(i,n)-1]=false;
if(get(n,j)!=0) pos[get(n,j)-1]=false;
if(get(start[i]+n/3, start[j]+n%3)!=0) pos[get(start[i]+n/3, start[j]+n%3)-1]=false;
}
for(int n=0; n<9; n++) if(pos[n]) {
set(i,j,n+1);
if(i==8 && j==8) return true;
if(guess(i)) return true;//recurse; gives Stackoverflow at this line
}
set(i,j,0);
return false;
}
答案 0 :(得分:1)
没有(现实的)方法将它放在循环中,但是你可以使用Dequeue方法(以堆栈的形式)绕过递归。
首先创建一个类,该类保存输入Sodoku-field的数字的当前状态。然后,而不是调用set(...)
创建该字段的副本并设置该副本中的值。然后将该副本放入Dequeue并终止该函数。
您的搜索循环将变为:
SodokuField field;
while (((field = dequeue.pollLast()) != null) && (field.isComplete() == false)) {
guess(field);
}
if (field != null) {
showSolution(field);
}
这种方法有两个好处:首先你不会再得到任何StackOverflowException,第二个:你可以轻松地将代码部分放在Runnable的run()
方法中,让多个线程等待{{ 3}}。
注意:基于堆栈的工作很重要,否则你会在找到解决方案之前创建所有可能的字段组合,因此很快会遇到内存问题。