Permutation Iterator in java

前端 未结 3 1695
天涯浪人
天涯浪人 2021-01-29 08:57

I want a class, that take in a possitive integer and produce a iterator that let me iterate through all possible of permutation of a list of possitive numbers under the positive

相关标签:
3条回答
  • 2021-01-29 09:35

    try this:

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.List;
    import java.util.stream.IntStream;
    
    public class Paermulator {
    
        private final List<int[]> list = new ArrayList<>();
    
        public Paermulator(int i) {
            int[] array = IntStream.iterate(0, x -> x + 1)
                    .limit(i)
                    .toArray();
            populateList(array, 0);
        }
    
        private void populateList(int[] array, int index) {
            if (index >= array.length - 1) {
                int[] temp = new int[array.length];
                System.arraycopy(array, 0, temp, 0, array.length);
                list.add(temp);
                return;
            }
    
            for (int i = index; i < array.length; i++) {
                int temp = array[index];
                array[index] = array[i];
                array[i] = temp;
    
                populateList(array, index + 1);
    
                temp = array[index];
                array[index] = array[i];
                array[i] = temp;
            }
        }
    
        public List<int[]> getList() {
            return list;
        }
    
        public Iterator<int []> getItrator() {
            return list.iterator();
        }
        // main method is for testing output
        public static void main(String[] args) {
            //printing output
            new Paermulator(5).getList().stream().forEach(x -> System.out.println(Arrays.toString(x)));
        }
    }
    

    This class accepts an int in constructor and creates an array and pass the array to populateList method this method populate the list with all possible permutations.
    and you can get Iterator using getIterator method .

    0 讨论(0)
  • 2021-01-29 09:36

    This is a better solution, inspired by https://stackoverflow.com/a/10117424/312172

    To achieve, instead of getting a list of elements that are jumbled, we focus on the choices we make when deducting elements from the list. give the function a size, and a number that is smaller than factorial(size); it will return a sequence of choices we need to make to get the permutation.

    for example:
    getTheIndexOfSelection(100,5)-> for a list of 5 elements, we want the 100th permutation.

    it should output: [4, 0, 2, 0, 0]

    it means, remove the element at index 4, for the list that got removed, remove element at 0 ....

    if the list is[1,2,3,4,5]; this will be the procujure:
    [1,2,3,4,5] remove index 4 -> 5
    [1,2,3,4] remove index 0 -> 1
    [2,3,4] remove index 2 -> 4
    [2,3] rovmove index 0 -> 2
    [3] remove index 0 -> 3
    all the element we removed sequentially is the permutation.

    /**
         * Feed this function a number, it gives you a sequence of choices 
         * to make a permutation. 
         * <br>
         * if this return [0,0,0,0]
         * it means remove element at 0, and then remove again... until 
         * reaches the end. 
         * @return
         * 
         * @param
         * len: the length of the list
         * n: the number that got match to a certain permutation. 
         */
        public static int[] getTheIndexOfSelection(int n, int size)
        {
            int[] lst = new int[size];
            return getTheIndexOfSelection( n,  size,  0, lst);
    
        }
    
    
    
    
     private static int[] getTheIndexOfSelection(int n, int size, int index, int[] lst)
        {
            if(size==1)
            {
                int[] result = {0}; // a list of one element, you can only choose the one that is in it
                // which is at index 0; 
                return result;
            }
    
            if(n >= factorial(size))return null; // This is not possible to do. 
    
            size-=1;
            int   firstchoice = n/factorial(size);
    
            lst[index]        = firstchoice;
    
            n = n-firstchoice*factorial(size);
    
            if(size>1)return getTheIndexOfSelection(n ,size, index+1, lst);
            return lst;
        }
    

    This is a better solution because:

    1. The speed really depends on the factorial function, assume factorial is super fast, this will be o(n).
    2. It matches numbers to permutation, making the expandable for things like map and iterator.
    3. It is not the full solution, the part that is left to solve do is pretty much trivial by now.
    0 讨论(0)
  • 2021-01-29 09:50

    An implementation using Heap's Algorithm. It compute next permutations on the fly. And have only one array copying

    
    
    import java.util.Arrays;
    import java.util.Iterator;
    
    class Permutator<E> implements  Iterator<E[]>{
    
        E[] arr1 = null;
        E[] arr2 = null;
        int size;
        int[] stack = null;
    
        int index = 0;
        public Permutator( E[] arr ){
    
            if( arr.length > 0 ){
                arr1 = arr;
    
                size = arr1.length;
                arr2 = Arrays.copyOf(arr1, size);
    
                stack = new int[size];
                Arrays.fill(stack, 0);
            }
        }
    
        @Override
        public boolean hasNext() {
            return (null != arr1 && arr1.length > 0);
        }
    
        @Override
        public E[] next() {
    
            // start computing.
            // We will return original array as value of last permutation.
            // This is to make "hasNext() " implementation easy.
            updateValue();
            return arr2;
        }
    
        protected void updateValue(){
    
            boolean bret = false;
    
            for( ; index < size ; ){
    
                if( stack[index] < index ){
    
                    if( index %2 == 0 ){
                        swap(0, index);
                    }else{
                        swap(stack[index], index);
                    }
    
                    stack[index]++;           
                    index = 0;
                    bret = true;
                    break;
                }else{
                    stack[index] = 0;
                    index++;
                }
            }
    
            if( !bret ){
                // No more permutation available. 
                // Set the original array as return value.
                // Also set arr1 = null , so that hasNext() will return false for next test
                arr2 = arr1;
                arr1 = null;
            }
        }
    
        private void swap (final int i, final int j) {
            E temp = arr2[i];
            arr2[i] = arr2 [j];
            arr2[j] = temp;
        }
    }
    
    
    

    Usage:

    
    public static void main(String[] args) {
    
            Permutator<Integer> perm = new Permutator<Integer>(new Integer[]{1,2,3, 4, 5});
            int count = 0;
            while(perm.hasNext()){
                System.out.println(Arrays.toString(perm.next()));
                count++;
            }
            System.out.println("total: " + count);
        }
    
    
    0 讨论(0)
提交回复
热议问题