嵌套循环转换为Java中的递归函数

时间:2016-07-02 09:23:47

标签: java recursion

我似乎无法弄清楚如何将这个嵌套循环转换为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次?

3 个答案:

答案 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} ],
]

这给了我以下信息:

  1. 当迭代到H{3}时,它会找到一个带有下一个位置的House,即4。
  2. 当迭代到H{4}时,它将创建第一个列表并存储之前重复位置为0,1,2,3的房屋。
  3. 到达H{4}后,它会找到另一个位置为House的{​​{1}},即H'{4},并创建第二个列表并存储之前迭代的房屋,H{4}除外。
  4. 当到达列表末尾时,它会返回H'{3}并再次迭代列表以创建第3和第4个列表。
  5. 从#2开始,我们知道:

    1. 我们需要创建一个列表来存储House if house position = 4
    2. 应该有一个buffer来存储House,其位置为0,1,2,3,之前是迭代的。 buffer[0]将存储H{0}buffer[1]将存储H{2}等。
    3. 从#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);