2015-10-20 98 views
1

Java中使用遞歸函數獲取從多組候選人中獲取的所有元素組合的最佳方法是什麼?一般而言,候選集的數量未定義,因此遞歸解決方案似乎適合於此任務。對於給定的套候選人的例子如何遞歸獲取Java中的所有組合?

[1,2] 
[3,4] 
[5,6,7] 

應該得到12種組合:

[1,3,5] [2,3,5] 
[1,4,5] [2,4,5] 
[1,3,6] [2,3,6] 
[1,4,6] [2,4,6] 
[1,3,7] [2,3,7] 
[1,4,7] [2,4,7] 

候選集被表示爲類型的名單列表:列出<名單<牛逼> >

回答

0

組合總數是候選集大小的乘積。每個結果集的大小等於候選集的數量。

您不需要該解決方案的遞歸。只需瀏覽每個候選集。在這個例子中,第一有兩個值,1個2的第一個6個的結果集(其中一半)獲得的第一個值作爲1,下一個半得到6.

到下一候選集合中,有兩個值,3和4.但是這一次,它們以3組而不是6組交替分配。因此,前3個結果集得到3個,接下來的3個集合得到4個,接下來的3個得到3個,依此類推。

下一個候選集有三個值:5,6,和7你會轉動它的價值分配每個現在結果集(每旋轉1個分配。)如果有多個候選或不同量的它們中的值,旋轉到下一個值之前分配的數量會發生變化。但是你可以用編程的方式來解決這個問題。

1

你不需要遞歸。只需使用集合列表的大小,然後使用每個集合的大小。你可以保持開放的結果,以增加更多的元素,以防萬一你在未來需要更多的組合,以防萬一你需要。

1

幾年前我遇到了同樣的問題。我通過里程錶遍歷結果列表來解決它。

里程錶中車輪的數量是輸入組的數量。每個輪子上的數字都是相應組的成員。要獲得下一個排列,請滾動最右側的里程錶輪。如果它轉身一路滾一個它的左等

例如:

Wheel 0 values: [1,2] 
Wheel 1 values: [3,4] 
Wheel 2 values: [5,6,7] 

開始與里程錶讀數(1,3,5)。前進到(1,3,6),(1,3,7)。然後滾動下一個輪子到(1,4,5),(1,4,6)和(1,4,7)。繼續。

里程錶車輪作爲指標

或者,你可以代表車輪作爲索引到相應的列表。

Wheel 0 values: [0,1] 
Wheel 1 values: [0,1] 
Wheel 2 values: [0,1,2] 

從里程錶讀數開始(0,0,0)。前進到(0,0,1),(0,0,2)。然後滾動下一個輪子到(0,1,0),(0,1,1)和(0,1,2)。繼續。對於每次讀數,請使用里程錶輪讀數作爲輸入列表中的索引轉換爲結果列表。

里程錶輪迭代器

作爲另一種選擇,你可以代表輪迭代器到輸入集合。這比前兩種方法更普遍。即使輸入集合不能被索引訪問,它也可以工作。而且它是可擴展的。這是我幾年前使用的方法。

0

謝謝大家的回覆。

安迪托馬斯,與里程錶非常有趣的想法。稍後再試一試。現在我已經按照ThatOneCloud的建議實現了它。

這裏就是我已經有了(整數物品;如果需要的話可以概括):

public List<List<Integer>> makeCombinations(List<List<Integer>> candidates) { 

    List<List<Integer>> result = new ArrayList<List<Integer>>(); 

    // calculate result size 
    int size = 1; 
    for (List<Integer> candidateSet : candidates) 
     size *= candidateSet.size(); 

    // make result 
    for (int i = 0; i < size; i++) 
     result.add(new ArrayList<Integer>()); 

    // fill result 
    int pos = 1; 
    for (List<Integer> candidateSet : candidates) 
     fillPosition(candidateSet, result, countRepeats(candidates, pos++)); 

    // return 
    return result; 
} 

public int countRepeats(List<List<Integer>> candidates, int pos) { 

    int repeats = 1; 
    for (int i = pos; i < candidates.size(); i++) 
     repeats *= candidates.get(i).size(); 
    return repeats; 
} 

public void fillPosition( List<Integer>  candidateSet, 
          List<List<Integer>>  result, 
          int      repeats) { 

    int idx = 0; 
    while (idx < result.size()) { 
     for (int item : candidateSet) { 
      for (int i = 0; i < repeats; i++) { 
       result.get(idx++).add(item); 
      } 
     } 
    } 
} 
0

而這裏的另一個版本(里程錶,安迪·托馬斯建議)

import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.List; 

public class Odometer<T> implements Iterable<List<T>> { 

    private class Wheel { 
     List<T> values; 
     int   idx = 0; 

     /** 
     * Create an odometer wheel from list of values 
     * @param v 
     */ 
     protected Wheel (List<T> v) { 
      if (v == null) throw new NullPointerException("can't create an instance of Wheel.class with null values"); 
      if (v.isEmpty()) throw new IllegalArgumentException("can't create an instance of Wheel.class with no values"); 
      this.values = v; 
     } 

     /** 
     * Get wheel value 
     * @return 
     */ 
     protected T value() { 
      return values.get(idx); 
     } 

     /** 
     * switch an odometer wheel one step 
     * @return TRUE - if a wheel have made full cycle and have switched to first item 
     */ 
     protected boolean next() { 
      if (idx >= values.size() - 1) { 
       idx = 0; 
       return true; 
      } else { 
       idx++; 
       return false; 
      } 

     } 
    } 

    /** 
    * list of wheels 
    */ 
    private List<Wheel> wheels = new ArrayList<Wheel>(); 

    /** 
    * Create an odometer from several lists of values 
    * (each List<T> is a list of values for one odometer wheel) 
    * @param values 
    */ 
    public Odometer(List<List<T>> values) { 
     for (List<T> v : values) 
      wheels.add(new Wheel(v)); 
    } 

    /** 
    * Get odometer value 
    * @return 
    */ 
    public List<T> get() { 
     List<T> result = new ArrayList<T>(); 
     for (Wheel wheel : wheels) { 
      result.add(wheel.value()); 
     } 
     return result; 
    } 

    /** 
    * Switch to next value 
    * @return TRUE if full cycle is finished 
    */ 
    public boolean next() { 
     for (int i = wheels.size() - 1; i >= 0; i--) 
      if (!wheels.get(i).next()) return false; 
     return true; 
    } 

    /** 
    * Reset odometer 
    */ 
    public void reset() { 
     for (Wheel wheel : wheels) 
      wheel.idx = 0; 
    } 

    /** 
    * Iterator 
    */ 
    @Override 
    public Iterator<List<T>> iterator() { 
     reset(); 
     Iterator<List<T>> it = new Iterator<List<T>>() { 
      private boolean last = false; 

      @Override 
      public boolean hasNext() { 
       return !last; 
      } 
      @Override 
      public List<T> next() { 
       List<T> result = get(); 
       last = Odometer.this.next(); 
       return result; 
      } 
      @Override 
      public void remove() { 
       throw new UnsupportedOperationException(); 
      } 
     }; 
     return it; 
    } 

    public static void main(String [] args) { 
     List<Integer> l1 = new ArrayList<Integer>(); l1.add(1); l1.add(2); 
     List<Integer> l2 = new ArrayList<Integer>(); l2.add(3); l2.add(4); l2.add(5); 
     List<Integer> l3 = new ArrayList<Integer>(); l3.add(6); l3.add(7); 
     List<List<Integer>> list = new ArrayList<List<Integer>>(); list.add(l1); list.add(l2); list.add(l3); 
     Odometer<Integer> odometer = new Odometer<Integer>(list); 
     for (List<Integer> value : odometer) { 
      System.out.println(value); 
     } 
    } 
} 
相關問題