我有一个程序,给定一个数组,返回其值的所有可能组合(排列?)。我递归地这样做。并且它计算好了,但是,我想要做的是,而不是每次迭代打印结果数组,我想将它附加到我之前声明的数组列表。
public static final int NUMBER_OF_CELLS = 3;
public static final int NUMBER_OF_ATTRIBUTES = 3;
// I want all possible combinations all elements 0, 1 and 2, taken 3 at a time
private ArrayList<State> states= new ArrayList<State>();
public void createAllPossibleStates() {
State state = new State(NUMBER_OF_CELLS);
setValues(0, state);
System.out.println(states); // This gives me a wrong ouput and I don't know why
}
public void setValues(int cell, State state) {
if(cell == NUMBER_OF_CELLS) {
// System.out.println(state.toString()); // Instead of this
states.add(state); // I want this. Append the array to an array list
}
}
else {
for(int i = 0; i < NUMBER_OF_ATTRIBUTES; i++) {
state.values[cell] = i;
setValues(cell + 1, state);
}
}
}
但最终Array List的结果包含所有可能的状态是错误的。而不是:
[[0, 0, 0],[0, 0, 1],[0, 0, 2],[0, 1, 0],[0, 1, 1],[0, 1, 2],[0, 2, 0],[0, 2, 1],[0, 2, 2],[1, 0, 0],[1, 0, 1],[1, 0, 2],[1, 1, 0],[1, 1, 1],[1, 1, 2],[1, 2, 0],[1, 2, 1],[1, 2, 2],[2, 0, 0],[2, 0, 1],[2, 0, 2],[2, 1, 0],[2, 1, 1],[2, 1, 2],[2, 2, 0],[2, 2, 1],[2, 2, 2]]
我明白了:
[[2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2]]
我不禁想知道为什么会这样。也许递归事实导致追加操作工作错误?
答案 0 :(得分:1)
<强>您好,强>
您总是将相同的State对象添加到ArrayList。 每个递归循环都在修改相同的State对象。
您必须在State类中实现clone:
@Override
protected State clone() throws CloneNotSupportedException {
State state = new State(NUMBER_OF_CELLS);
System.arraycopy(this.values, 0, state.values, 0, this.values.length);
return state;
}
将states.add(state);
替换为states.add(state.clone());
答案 1 :(得分:1)
您只有1个State
实例,并且您将其传递给调用堆栈,对其进行修改,然后将其多次添加到列表中(每次递归终止一次)。当然,由于只涉及一个对象,它将具有任何状态(没有双关语意图)是给予它的最后一个状态。
如果不修改太多代码,则需要复制State
对象并将副本添加到列表中 - 以便在将其添加到列表时永久捕获状态清单。
有一些标准的方法可以做到这一点,但也许最容易理解和最常用的是复制构造函数:
public State(State state) {
this.values = Arrays.copyOf(state.values, state.values.length);
// copy over whatever other fields you need
}
然后在你的代码中:
states.add(new State(state));