Perfect Shuffle Algorithm

In-shuffle Algorithm

initial deck:       1 2 3 4 5 6 7 8
shuffled deck:      5 1 6 2 7 3 8 4

suppose i is the index of element in the original array, j is the index of that element in the new array.

We can easily get the formation: i, j starts with 1

j= 2*i mod (2*n+1)

Reference papaer:

[A Simple In-Place Algorithm for In-Shuffle](http://att.newsmth.net/att.php?p.1032.47005.1743.pdf)

Explanation:

A = [1, 2, 3, 4, 5, 6, ...,n, n+1, n+2, n+3, n+4,...,2*n]

Find 2*m = 3^k-1 such that 3^k<= 2n < 3^(k+1)

[1, 2, 3,..., m, m+1, m+2,..., n,    n+1, n+2, n+3,..., n+m, n+m+1,..., 2*n]
                  |                                      |
                  |....... Right shift m step ...........|

[1, 2, 3,..., m, n+1, n+2,....., n+m,      m+1, m+2,..., n,  n+m+1,..., 2*n]

do for remaining [m+1, m+2,..., n, n+m+1,..., 2*n]

Out shuffle:

Given a 2n size array [a1, a2, a3, a4,..,an, b1, b2, b3,...,bn] shuffle it in place to [a1, b1, a2, b2,...,an, bn].

Here In place means O(n) time complexity and O(1) space complexity.

initial deck:       0 1 2 3 4 5 6 7
shuffled deck:      0 4 1 5 2 6 3 7

Analysis

suppose i is the index of element in the original array, j is the index of that element in the new array. We can easily get the formation:

j=
F(i)=2*i          if i<n 
     2*(i-n)+1    if i>=n

start from any index, we keep applying the function F(i) and We get the sequence of index by shifting which we can arrange all the element in this sequence from original position to the new array position in O(1) space complexity.

Implementation

public void shuffle(int[] origin){
    if(origin==null || origin.length<=2) return;
    int n=origin.length/2;
    boolean[] visited=new boolean[origin.length];
    for(int i=0;i<2*n;i++){
      if(!visited[i]) cycle(i,origin,visited,n);
    }
}

public void cycle(int start, int[] arr, boolean[] visited, int n){
    visited[start]=true;
    int i=start<n?2*start:(2*(start-n)+1);//Function 'F'
    int prevalue=arr[start];
    while(i!=start){
        visited[i]=true;
        int tmp=arr[i];
        arr[i]=prevalue;
        prevalue=tmp;
        i=i<n?2*i:(2*(i-n)+1);
    }
    arr[i]=prevalue;
  }
def shuffle(A):
    N = len(A)/2
    movetoidx = lambda x: 2*x if x<N else 2*(x-N)+1
    for i in range(N-2):
        p = i
        prev = A[p]
        while movetoidx(p) != i:
            A[movetoidx(p)], prev = prev, A[movetoidx(p)]
            p = movetoidx(p)
        A[movetoidx(p)], prev = prev, A[movetoidx(p)]
    return A

def p(N):
    movetoidx = lambda x: 2*(x-N) if x>=N else (2*x+1)
    visited = set()
    ans = []
    for i in range(2*N):
        if i in visited:
            continue
        tmp = [i]
        p = i
        while movetoidx(p)!=i:
            tmp.append(movetoidx(p))
            p = movetoidx(p)
        if len(tmp)>1:
            ans.append(tmp[0])
        visited.update(tmp)
    return ans

results matching ""

    No results matching ""