【洗牌算法】Fisher-Yates Shuffle

  这里记录了一些有趣的算法,http://www.keithschwarz.com/interesting/,里边就包括洗牌算法 Fisher-Yates Shuffle
  算法目的,是在一个数组中,将所有元素等概率随机打乱,就像完美的洗牌一样。
  算法流程就是,在长度为 n 的数组 arr 中,第一次在 [ 0, n-1 ] 中随机出一个位置 i,将 arr[i] 和 arr[0] 交换,第二次,在 [ 1, n-1 ] 中随机出一个位置 i,将 arr[i] 和 arr[1] 交换,以此类推,执行 n - 1 次。
  数学证明:
1、每个数随机到位置 0 的概率很明显是 1 n \frac {1}{n} n1
2、每个数随机到位置 1 的概率是 n − 1 n ∗ 1 n − 1 = 1 n \frac {n - 1}{n}\ast\frac {1}{n - 1} = \frac {1}{n} nn1n11=n1
3、以此类推,每个数随机到每个位置的概率都是 1 n \frac {1}{n} n1
  代码如下:

/**************************************************************************
 * File: RandomShuffle.hh
 * Author: Keith Schwarz (htiek@cs.stanford.edu)
 *
 * An implemention of a function for randomly permuting the elements of a
 * sorted range.  The algorithm is an implementation of the Fisher-Yates
 * shuffle (also called the Knuth shuffle), which works by randomly selecting
 * an element from the the array and swapping it to the front, then recursively
 * repeating the process on the rest of the array.  It runs in linear time
 * and with only constant space.
 *
 * This implementation, by default, works using the system rand function,
 * which is not ideal if cryptographic randomness is desired.  Consequently,
 * like the STL algorithm random_shuffle, the algorithm allows for a custom
 * random generator to be passed into the function.
 */
#ifndef RandomShuffle_Included
#define RandomShuffle_Included

#include <algorithm> // For iter_swap
#include <cstdlib>   // For rand

/**
 * Randomly permutes the elements in the range [begin, end), using the system
 * rand function as a source of randomness.
 */
template <typename RandomIterator>
void RandomShuffle(RandomIterator begin, RandomIterator end);

/**
 * Randomly permutes the elements in the range [begin, end), 
 * using the provided callback as a source of randomness.
 * The generator should be callable as a nullary function which produces a uniformly-distributed
 * random value over a range at least as large as the input range.
 */
template <typename RandomIterator, typename RandomGenerator>
void RandomShuffle(RandomIterator begin, RandomIterator end, RandomGenerator rnd);

/* Main implementation of the algorithm. */
template <typename RandomIterator, typename RandomGenerator>
void RandomShuffle(RandomIterator begin, RandomIterator end, RandomGenerator rnd) {
	for (RandomIterator itr = begin; itr != end; ++itr)
		std::iter_swap(itr, itr + rnd() % (end - itr));
}

/* Default implementation just uses rand. */
template <typename RandomIterator>
void RandomShuffle(RandomIterator begin, RandomIterator end) {
	RandomShuffle(begin, end, std::rand);
}

#endif

LeetCode - 384. Shuffle an Array

  这道题就是实现洗牌算法,代码如下:

class Solution {
public:
    vector<int> origin, cur;
    Solution(vector<int>& nums) : origin(nums), cur(nums) {
        
    }
    
    /** Resets the array to its original configuration and return it. */
    vector<int> reset() {
        return origin;
    }
    
    /** Returns a random shuffling of the array. */
    vector<int> shuffle() {
        const int len = cur.size();
        for(auto ite = cur.begin(); ite != cur.end(); ++ite)
            swap(*ite, *(ite + rand() % (cur.end() - ite)));
        return cur;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值