Shuffle an array as many as possible

前端 未结 8 1371
一向
一向 2020-12-07 05:21

I have an array like this

[0,2,3]

The possible shuffling of this array are

[0,2,3], [2,3,0], [3,0,2], [3,2,0], [0,3,2],         


        
8条回答
  •  青春惊慌失措
    2020-12-07 05:54

    For an array of length n, we can precompute the number of possible permutations. It's n! (n factorial)

    function factorial(n){ return n<=0?1:n*factorial(n-1);}
    //There are better ways, but just for illustration's sake
    

    And, we can create a function which maps an integer p between 0...n!-1 to a distinct permutation.

    function map(p,orgArr){
     var tempArr=orgArr.slice(); //Create a copy
     var l=orgArr.length;
     var permArr=[];
     var pick; 
     do{
      pick=p%l; //mod operator
      permArr.push(tempArr.splice(pick,1)[0]); //Remove item number pick from the old array and onto the new
      p=(p-pick)/l;
      l--;
     }while(l>=1)
     return permArr;  
    }
    

    At this point, all you need to do is create an array ordering=[0,1,2,3,...,factorial(n)-1] and shuffle that. Then, you can loop for(var i=0;i<=ordering.length;i++) doSomething(map(ordering[i],YourArray));

    That just leaves the question of how to shuffle the ordering array. I believe that's well documented and outside the scope of your question since the answer depends on your application (i.e. is pseudo random good enough, or do you need some cryptographic strength, speed desired, etc...). See How to randomize (shuffle) a JavaScript array? and many others.

    Or, if the number of permutations is so large that you don't want to create this huge ordering array, you just have to distinctly pick values of i for the above loop between 0-n!-1. If just uniformity is needed, rather than randomness, one easy way would be to use primitive roots: http://en.wikipedia.org/wiki/Primitive_root_modulo_n

提交回复
热议问题