Shuffle & next-permutation

@vrqq  November 24, 2017

Fisher-Yates shuffle Modern method.

https://en.wikipedia.org/wiki/Fisher-Yates_shuffle#Modern_method
易于理解,从最后一个开始loop,在他之前(包括他本身)随便找一个,跟他swap。

vector<int> shuffle(vector<int> a) {
    for (int i=a.size()-1; i>0; i--) {
        int p = rand()%(i+1);
        swap(a[p],a[i]);
    }
    return a;
}

Next Permutation

先来看全排列,n个数的全排列有n!个。

// Calling perm(0) to start.
int a[]={1,2,3,4}, n=4;
void perm(int p) {
    if (p==n-1) {
        for (int i=0; i<n; i++)
            cout<<a[i]<<" ";
        cout<<endl;
    }
    for (int i=p; i<n; i++) {
        swap(a[p],a[i]);
        perm(p+1);
        swap(a[i],a[p]);
    }
}

原理就是第一次recursion,把第一位和他后面(包括他自己)的数换一下,然后进行下一位的recursion,然后再换回来。

https://en.wikipedia.org/wiki/Permutation
http://bangbingsyb.blogspot.com/2014/11/leetcode-next-permutation.html
这个next permutation就有点神奇了,还是STL里的,不如换个思路理解一下,参见上述链接。
所谓next permutation,就是现在已经有个排列了(假定刚开始是升序排列),用这几个数排列一下,找“比现在这个排列就大一点点的排列”。
e.g.: 4 3 2 1 => is the most largest permutation.

  4 2 3 1 => move 'number3' to the position of 'number2'.
  ==> 4 3 (2 1). and resort 
int a[]={1,2,3,4}, n=4;
void nextPerm () {
    int pos1, pos2;
    for (pos1=n-2; pos1>=0; pos1--)
        if (a[pos1]<a[pos1+1])
            break;
    if (pos1==-1) {// e.g. 4 3 2 1
        reverse(a,a+n);
        return ;
    }
    for (pos2=n-1; pos2>pos1; pos2--)
        if (a[pos2]>a[pos1])
            break;
    swap(a[pos1],a[pos2]);
    //after swap, a[pos1+1 -> n] must keep its order (non-increase),
    //so we just need to reverse it simply to get the minimum sequence.
    reverse(a+pos1+1,a+n);
}

添加新评论