两次笔试都遇到这个问题,出镜率挺高(事实上任何一种一页纸能写完的算法都可能在面试笔试中遇到,加油骚年!)

分析:本质上是1~n的随机序列问题

方法2(推荐):先对数组进行初始化,然后为每个位置生成一个随机位置进行交换,共交换n次,其中n越大越接近随机。这也是C++的STL<algorithm>库中的random_shuffle()函数的思想

注意:rand()%(i+1); 对i+1取余而不是对n

void swap(int &a, int &b){
    int tmp = a;
    a = b;
    b = tmp;
}
void shuffle_2(int a[], int n){
    for(int i=0; i<n; i++)
        a[i] = i+1;
    for(int i=n-1;i>0; --i){   //倒序显然比正序好, i取不到0,a[0]没必要交换
        int num =rand()%(i+1); //注意这里是对i+1取余 从a[0]到a[i]中取待交换位置,不是对54
        if(num!=i)
            swap(a[num],a[i]);
    }
}

 

 

想法一:将54个数依次放到随机的位置,关键是每次找到一个新的随机位置

①每次产生一个0~53的随机数,看这个位置是否有数,如果已经被占了,则继续;否则选定此位置,数组值设置为n(代表某张牌如红桃K)

②反复执行,直到所有位置都有数。

以下是代码(测试通过)

void shuffle(int arr[], int n){
    int pos,card;
    memset(arr, 0, sizeof(int)*n); //类似malloc,只是分配空间并初始化为0
    for(card=1;card<=n; card++){
        do{
            pos = rand()%(n); //产生 0~53的随机数, 随机取位置,也可以下边这样写,显然取余简单
                                //pos = rand()/(RAND_MAX + 1)* 53 
        } while (arr[pos]!=0);
        arr[pos] = card;
    }
}

void main()
{
    const int num=54;
    int a[num];
    shuffle(a,num);
    for(int i=0;i<54;i++)
        cout << a[i] << " ";
    cout << endl;
}

 

问题:越到后边,寻找新的随机位置会越难,如果n数量级非常大不可取

 

 

参考:洗牌程序的两种实现方法比较

随机问题之--洗牌算法(JS版本)

 

posted on 2014-05-24 19:50  zhangxh_Doris  阅读(343)  评论(0编辑  收藏  举报