我是java的新手,我最近决定学习递归。我必须使用递归方法解决这个难题。 拼图是一个整数列表,您从第一个元素开始,目标是到达最后一个元素,即始终为零。现在你必须在列表中向右或向左移动,你可以这样做的次数取决于你当前所在的元素。您也不能移动到列表之外,也不能使用subList。我的方法是想看看给定的谜题是否可以解决。当前代码有StackoverFlow,我不知道如何解决它
答案 0 :(得分:3)
该算法存在一些问题。
方法'isSolveable'做的最后一件事是返回前向或后向可解决性。而不是返回,首先尝试前向可解决性,然后如果失败,尝试向后可解决性。
'BeenOn'列表未传递给每个isSolveable()方法调用,因此每次调用该方法时它总是为空。你可以在第一次通话时创建一个并在每次调用方法时传递它。
你也不会检查它的界限是否正确。 list.size()总是比列表中最后一个位置的实际索引大1,因为列表从0开始,而不是1.所以你的最后一个索引是board.size() - 1
public static boolean isSolvable(int index, List<Integer> board, List<Integer> visitedIndices) {
int lastIndex = board.size() - 1;
if (index == lastIndex) {
// Last index. solved
return true;
}
if (index > lastIndex || index < 0 || visitedIndices.contains(index)) {
// Outside list or previously vistied, failed to solve
return false;
}
visitedIndices.add(index);
int nextIndexForward = index + board.get(index);
int nextIndexBackward = index - board.get(index);
return isSolvable(nextIndexForward, board, visitedIndices)
|| isSolvable(nextIndexBackward, board, visitedIndices);
}
答案 1 :(得分:2)
DangerDan的回答包含所有信息。作为替代方案,我想展示一个基于类的解决方案,而不是传递参数。这样它有点清洁:
public class Puzzle {
private final List<Integer> board;
private final List<Integer> visitedIndices = new ArrayList<Integer>();
public Puzzle(List<Integer> board) {
this.board = board;
}
public boolean isSolvable() {
return isSolvableAtIndex(0);
}
private boolean isSolvableAtIndex(int index) {
int lastIndex = board.size() - 1;
if(index == lastIndex) {
return true;
}
if(index < 0 || index > lastIndex || visitedIndices.contains(index)) {
return false;
}
visitedIndices.add(index);
int step = board.get(index);
return isSolvableAtIndex(index + step) || isSolvableAtIndex(index - step);
}
}
使用示例:
Puzzle puzzle = new Puzzle(Arrays.asList(5, 5, 1, 1, 1, 2, 0));
System.out.println("Puzzle is solvable: " + puzzle.isSolvable() ? "yes" : "no"); // "Puzzle is solvable: yes"