Java递归组合函数与迭代等价

时间:2014-04-17 10:38:53

标签: java recursion iteration

我有递归合并功能:

static void combinations2(String[] arr, int len, int startPosition, String[] result) {

    if (len == 0) {
        for (String n : result) {
            System.out.print(n + "  \n");

        }

        return;
    }

    for (int i = startPosition; i <= arr.length - len; i++) {
        result[result.length - len] = arr[i];
        combinations2(arr, len - 1, i + 1, result);
    }
}

输入:

 arr = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5"} - input array e.g.
 len = 3 - length of each combination
 startPosition = 0
 result - result of each combination

输出:

Item 1  
Item 2  
Item 3  

Item 1  
Item 2  
Item 4  

Item 1  
Item 2  
Item 5  

Item 1  
Item 3  
Item 4  

Item 1  
Item 3  
Item 5  

Item 1  
Item 4  
Item 5  

Item 2  
Item 3  
Item 4  

Item 2  
Item 3  
Item 5  

Item 2  
Item 4  
Item 5  

Item 3  
Item 4  
Item 5 

我应该怎么做才能将其改为迭代替代方案?我读了一下堆栈,我写了几行...但是返回功能怎么样?如何处理它?<​​/ p>

我做过这样的事情:

static void combinations2(String[] arr, int len, int startPosition, String[] result) {
        Stack<Integer> stos = new Stack<>();
        stos.push(startPosition);
        stos.push(len);

        int i = 0;
        while (!stos.isEmpty()) {
            len = stos.pop();
            startPosition = stos.pop();

            if (len == 0) {
                for (String n : result) {
                    System.out.print(n + "  \n");
                }            

                System.out.println("    ");
                stos.push(startPosition);
                stos.push(len+1);
            } else {

                for (i = startPosition; i <= arr.length - len; i++) {
                    result[result.length - len] = arr[i];

                    //combinations2(arr, len - 1, i + 1, result);
                    stos.push(i + 1);
                    stos.push(len - 1);
                    break;

                }
            }  
        }
    }

我有输出:

Item 1  
Item 2  
Item 3  

Item 1  
Item 2  
Item 4  

Item 1  
Item 2  
Item 5 

有人可以告诉我如何生成后续步骤吗?

1 个答案:

答案 0 :(得分:0)

以下类是Iterable,它返回组合。请参阅main方法以供使用。运行main方法进行测试。

组合是懒洋洋地创建的,因此从10​​000000的池中读取10个元素的前100个组合将不会很慢。

这个类也短路任何对不可能场景的探索,即对于5个元素中的3个元素的组合,将第4个元素放置在第一个位置是没有意义的,因为这将导致第5个元素处于第二个位置,并且没有留下任何元素最后一个位置。

通常,递归算法的迭代版本使用堆栈来模拟传递给同一函数的变量。

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

    private final List<T> items;
    private final int size;

    public static <T> Combinations<T> of(List<T> items, int size) {
        return new Combinations<T>(items, size);
    }

    private Combinations(List<T> items, int size) {
        if (items.size() < size) throw new IllegalArgumentException();
        this.items =  items;
        this.size = size;
    }

    public Iterator<List<T>> iterator() {
        return new Iterator<List<T>>() {        
            private final int[] positions = new int[size];              
            private boolean more = true;
            {
                for(int i = 0;i < positions.length;i++) {
                    positions[i] = i;
                }
            }

            public boolean hasNext() {
                return more;
            }

            public List<T> next() {
                if (!more) throw new NoSuchElementException();
                List<T> ret = new ArrayList<T>();
                for (int i = 0;i < positions.length;i++) {
                    ret.add(items.get(positions[i]));
                }
                int advanceIdx = positions.length - 1;
                while(advanceIdx > -1) {
                    if (positions[advanceIdx] == items.size() - size + advanceIdx) {
                        advanceIdx--;
                    } else {
                        positions[advanceIdx]++;
                        for (int i = 1;i + advanceIdx < positions.length;i++) {
                            positions[advanceIdx+i] = positions[advanceIdx] + i; 
                        }
                        return ret;
                    }
                }
                more = false;
                return ret;
            }

            public void remove() {
                throw new UnsupportedOperationException();
            }

        };
    }

    public static void main(String[] args) {
        for(List<String> s : Combinations.of(Arrays.asList("A", "B", "C", "D", "E"), 3)) {
            System.out.println(s);
        }
    }
}