Johnson Trotter Algorithm

前端 未结 4 636
醉酒成梦
醉酒成梦 2020-12-06 23:53

Overview:

I am trying to implement the Johnson Trotter Algorithm in Java so that I can solve a problem on Project Euler. I have looked and looked bu

相关标签:
4条回答
  • 2020-12-07 00:00

    I looked at the suggested link with Even's speedup and think it is unnecessarily inefficient, using compares. My understanding is that Even's speedup means you don't need compares.

    Here's my code; this iterative form (unlike the recursive solution) allows you to call a getNext iterator to generate and return the next permutation.

    // Johnson-Trotter algorithm (http://en.wikipedia.org/wiki/Steinhaus%E2%80%93Johnson%E2%80%93Trotter_algorithm)
    public class Permuter {
        private int[] perms;
        private int[] indexPerms;
        private int[] directions;
        private int[] iSwap;
        private int N; //permute 0..N-1
        private int movingPerm=N;
    
        static int FORWARD=+1;
        static int BACKWARD=-1;
    
    
        Permuter(int N) {
            this.N = N;
            perms =  new int[N];     // permutations
            indexPerms = new int[N];     // index to where each permutation value 0..N-1 is
            directions = new int[N];     // direction = forward(+1) or backward (-1)
            iSwap = new int[N]; //number of swaps we make for each integer at each level
            for (int i = 0; i < N; i++) {
                directions[i] = BACKWARD;
                perms[i]  = i;
                indexPerms[i] = i;
                iSwap[i] = i;
            }
            movingPerm = N;
        }
    
        int[] getNext() {
            //each call returns the next permutation
            do{
                if (movingPerm == N) {
                    movingPerm--;
                    return perms;
                } else if (iSwap[movingPerm] > 0) {
                    //swap
                    int swapPerm = perms[indexPerms[movingPerm] + directions[movingPerm]];
                    perms[indexPerms[movingPerm]] = swapPerm;
                    perms[indexPerms[movingPerm] + directions[movingPerm]] = movingPerm;
                    indexPerms[swapPerm] = indexPerms[movingPerm];
                    indexPerms[movingPerm] = indexPerms[movingPerm] + directions[movingPerm];
                    iSwap[movingPerm]--;
                    movingPerm=N;
                } else {
                    iSwap[movingPerm] = movingPerm;
                    directions[movingPerm] = -directions[movingPerm];
                    movingPerm--;
                }
            } while (movingPerm > 0);
            return null;
        }
    
    0 讨论(0)
  • 2020-12-07 00:02

    Here is the java code for Johson Trotter Algorithm

    public class PermutationGenerator {

    public void generatePermute(int N)
    {
            ModifiedInteger[] permute=new ModifiedInteger[N];
            int noOfPermutation=0;
            for(int i=0;i<N;i++){
                permute[i]=new ModifiedInteger(i,i+1,true);
            }
            System.out.print(++noOfPermutation+" ");
            for(ModifiedInteger element:permute){
                System.out.print(element.value+",");
            }
            System.out.println();
            ModifiedInteger mobile;
            while((mobile=largestMobile(permute))!=null)
            {
                //System.out.println("Largest Mobile is val- "+mobile.value+" index is "+mobile.index);
                swap(mobile,permute);
                //System.out.println("After Swap Largest Mobile is val- "+mobile.value+" index is "+mobile.index);
                reverse(permute,mobile);
                System.out.print(++noOfPermutation+" ");
                for(ModifiedInteger element:permute){
                    System.out.print(element.value+",");
                }
                System.out.println();
            }
    
    }
    public void reverse(ModifiedInteger[] sequence,ModifiedInteger largestMobile){  
        for(ModifiedInteger element:sequence){
            if(element.value>largestMobile.value){
                element.direction=!element.direction;
    
            }
    
        }
    }
    public void swap(ModifiedInteger largestMobileInteger,ModifiedInteger[] sequence)
    {
        ModifiedInteger temp=largestMobileInteger;
        if(largestMobileInteger.direction){
            sequence[largestMobileInteger.index]=sequence[largestMobileInteger.index-1];
            sequence[largestMobileInteger.index-1]=temp;
            sequence[largestMobileInteger.index].index+=1;
            largestMobileInteger.index-=1;
        }
        else{
            sequence[largestMobileInteger.index]=sequence[largestMobileInteger.index+1];
    
            sequence[largestMobileInteger.index+1]=temp;
            sequence[largestMobileInteger.index].index-=1;
            largestMobileInteger.index+=1;
        }
    
    
    }
    public ModifiedInteger largestMobile(ModifiedInteger[] sequence){
        ModifiedInteger largestMobile=null;
        int count=0;
        for(ModifiedInteger element:sequence){
            if(element.direction&&count!=0&&element.value>sequence[count-1].value)
            {
                if(largestMobile==null){
                    largestMobile=element;
                }
                else if(largestMobile.value<element.value){
                    largestMobile=element;
                }
    
            }
            else if(!element.direction&&count<sequence.length-1&&element.value>sequence[count+1].value)
            {
                if(largestMobile==null){
                    largestMobile=element;
                }
                else if(largestMobile.value<element.value){
                    largestMobile=element;
                }
    
            }
            count++;
        }
    
        return largestMobile;
    
    
    
    }
    //boolean direction-left-true;right-false
    public class ModifiedInteger
    {
        int value;
        int index;
        private boolean direction;
        ModifiedInteger(int index,int value,boolean direction){
            this.index=index;
            this.value=value;
            this.direction=direction;
        }
        public boolean getDirection() {
            return direction;
        }
        public void setDirection(boolean direction) {
            this.direction = direction;
        }
    }
    public static void main(String args[]){
    
        PermutationGenerator obj=new PermutationGenerator();
        obj.generatePermute(5);
    }
    

    }

    0 讨论(0)
  • 2020-12-07 00:04

    You can even download the complete java source code for this, with Even's speedup from here

    0 讨论(0)
  • 2020-12-07 00:11

    Although you are not posting the complete code here (how you decide if an element is mobile or immobile would be helpful), I suspect your error comes from here:

     public int getLargestMobileIndex(ArrayList<Element> elements)
          {
             int maxIndex = 0;
    
             for(int i = 0; i < elements.size(); i++)
             {
                if(elements.get(i).isMobile() && i > maxIndex) //<---------- It seems that 
                // you should compare the i-th element to the maxIndex-th element, not i and
                // maxIndex
                {
                   maxIndex = i;
                }
             }
    
             return maxIndex;
          }
    

    Since the algorithm said find the largest mobile element K.

    Also, I suspect there are problems for your isMobile method, but cannot be sure.

    Hope this helps!

    0 讨论(0)
提交回复
热议问题