我似乎无法弄清楚如何将这个嵌套循环转换为Java中的递归函数?
ArrayList<House[]> houseList = new ArrayList<House[]>();
for (House h0 : houses) {
if (h0.getPosition() == 0) {
for (House h1 : houses) {
if (h1.getPosition() == 1) {
for (House h2 : houses) {
if (h2.getPosition() == 2) {
for (House h3 : houses) {
if (h3.getPosition() == 3) {
for (House h4 : houses) {
if (h4.getPosition() == 4) {
House[] list = new House[]{h0,h1,h2,h3,h4};
houseList.add(list);
}
}
}
}
}
}
}
}
}
}
此时house对象包含133个元素,嵌套循环执行后给出的组合给了我9810801种可能性。 如何以递归方式编写它可以使用超过5次?
答案 0 :(得分:1)
你有一个House
的列表,其位置为0,1,2,3,4。让我使用H{i}
的注释来表示位置为i且0 <=的房子我&lt; = 4。
如果您的输入列表是
[ H{0}, H{1}, H{2}, H{3}, H'{3}, H{4}, H'{4} ]
H'
是另一个房子
结果是
[
[ H{0}, H{1}, H{2}, H{3}, H{4} ],
[ H{0}, H{1}, H{2}, H{3}, H'{4} ],
[ H{0}, H{1}, H{2}, H'{3}, H{4} ],
[ H{0}, H{1}, H{2}, H'{3}, H'{4} ],
]
这给了我以下信息:
H{3}
时,它会找到一个带有下一个位置的House
,即4。H{4}
时,它将创建第一个列表并存储之前重复位置为0,1,2,3的房屋。H{4}
后,它会找到另一个位置为House
的{{1}},即H'{4}
,并创建第二个列表并存储之前迭代的房屋,H{4}
除外。 H'{3}
并再次迭代列表以创建第3和第4个列表。从#2开始,我们知道:
House
if house position = 4 buffer
来存储House
,其位置为0,1,2,3,之前是迭代的。 buffer[0]
将存储H{0}
,buffer[1]
将存储H{2}
等。从#3开始,我们知道:
如果到达位置4的House
,列表将进一步迭代,直到到达列表的末尾。
我们可以有如下基本功能:
public static List<House[]> foo(House[] houses, List<House> buffer) {
List<House[]> list = new ArrayList<House[]>();
for (House house : houses) {
if (house.getPosition() == buffer.size()) {
buffer.add(house);
if (house.getPosition() == 4) {
list.add(buffer.toArray(new House[buffer.size()]));
buffer.remove(buffer.size() - 1);
}
}
}
return list;
}
以上是做什么的?
for (House house : houses) {
if (house.getPosition() == buffer.size()) {
buffer.add(house);
一开始,buffer
为空,大小为0.如果找到位置为0的House
,则会将其存储到buffer
和{{1} } size变为1.当列表迭代到位置= 1(buffer
大小)的下一个House
时,它将被存储。否则,找到符合条件的另一个buffer
。
House
如上所述,如果if (house.getPosition() == 4) {
list.add(buffer.toArray(new House[buffer.size()]));
buffer.remove(buffer.size() - 1);
}
位置为4,则会创建一个列表以将House
存储在缓冲区中。House
将删除最后一个buffer.remove(buffer.size() - 1)
位置4使得另一个House
可以存储到House
。
到目前为止,我们的函数中没有递归调用,因为位置为4的buffer
的情况不需要它。
让我们回顾#1和#4。我们知道:
如果到达位置不是4的House
,它会找到一个带有下一个位置的House
,并在迭代到位置4的House
时创建一个列表。
这意味着如果House
的位置不是4,我们将调用我们的基函数。因此,我们可以按如下方式修改我们的函数:
House
总之,我们有两个问题的案例。一个是处理位置4的public static List<House[]> foo(House[] houses, List<House> buffer) {
List<House[]> list = new ArrayList<House[]>();
for (House house : houses) {
if (house.getPosition() == buffer.size()) {
buffer.add(house);
if (house.getPosition() == 4) { // base case, no recursive call
list.add(buffer.toArray(new House[buffer.size()]));
buffer.remove(buffer.size() - 1);
} else { // recursive case
list.addAll(foo(houses, buffer));
}
}
}
if (buffer.size() > 0) {
buffer.remove(buffer.size() - 1);
}
return list;
}
的基本情况,另一个情况是处理{4}以外需要递归调用的位置House
。
递归函数通常将问题划分为案例。该函数在较小的House
列表上递归调用自身,直到达到基本情况。希望这可以提供帮助。
答案 1 :(得分:1)
因为@Wilson问我是怎么做的,所以这里的方法适用于输入中的任何position
值,即使它们不是连续的。拨打电话:
List<House[]> houseTupleList = new HouseTupleListBuilder()
.addAll(houses)
.build();
输出元组将按升序包含填充位置的值。
请注意,如果输入中缺少位置编号(例如,在示例中只有位置为0,1,3,4的房屋),此代码将很乐意仅使用当前值生成元组(例如,在我的例如,它们将是4元组)。如果您不希望这样,则应为所有预期位置expectPosition(i)
调用构建器的方法i
。然后,如果输入缺少任何位置,则输出将为空,就像OP的版本一样。
class HouseTupleListBuilder {
private final NavigableMap<Integer, List<House>> housesByPosition = new TreeMap<>();
HouseTupleListBuilder addAll(Collection<House> houses) {
for (House house : houses) {
expectPosition(house.getPosition());
housesByPosition.get(house.getPosition()).add(house);
}
return this;
}
HouseTupleListBuilder expectPosition(int i) {
housesByPosition.putIfAbsent(i, new ArrayList<>());
return this;
}
List<House[]> build() { return new TupleEnumerator().enumeration(); }
private class TupleEnumerator {
private final Map<Integer, House> houseByPosition = new TreeMap<>();
private final List<House[]> tuples = new ArrayList<>();
private void enumerateFor(NavigableSet<Integer> positions) {
if (positions.isEmpty()) {
tuples.add(houseByPosition.values().toArray(new House[0]));
return;
}
int first = positions.first();
for (House house : housesByPosition.get(first)) {
houseByPosition.put(first, house);
enumerateFor(positions.tailSet(first, false));
}
}
private List<House[]> enumeration() {
enumerateFor(housesByPosition.navigableKeySet());
return tuples;
}
}
}
答案 2 :(得分:0)
事实上@Wilson的回答毕竟不正确。经过一些反复试验后,我自己想出了一个解决方案。这是代码的递归函数:
private void recursiveFunc(ArrayList<House> houses,ArrayList<House[]> resultList,House[] tempList, int pos, int maxPos) {
for (House h : houses) {
if (h.getPosition() == pos) {
tempList[pos] = h;
if (pos < maxPos-1) {
recursiveFunc(houses,resultList,tempList,pos+1,maxPos);
}
else if (pos == maxPos-1) {
House[] resultHouse = new House[maxPos];
for (int i=0; i<maxPos; i++) resultHouse[i] = tempList[i];
resultList.add(resultHouse);
}
}
}
}
我按如下方式执行该功能:
recursiveFunc(houses,solutionList,new House[numberOfPositions],0,numberOfPositions);