【面试向】从洗牌算法说起
Fisher-Yates shuffle
Durstenfeld's in-place version
void FY_shuffle(vector<int>& a, int n) {
default_random_engine e;
// seed e
for (int i = n - 1; i > 0; --i) {
uniform_int_distribution<int> d(0, i);
int index = d(e);
swap(a[i], a[index]);
}
}
现在问题是如何给随机数引擎 e
一个种子(seed)。常见的办法是用系统时间:std::time(nullptr)
或者 std::chrono::system_clock::now().time_since_epoch().count()
。但是这种方法有争议,见 https://stackoverflow.com/q/36663027/6052725。
Inside-out version
In this version, one successively places element number \(i\) of the source array into a random position among the first \(i\) positions in the target array, after moving the element previously occupying that position to position \(i\).
void inside_out_shuffle(const vector<int>& source, vector<int>& a, int n) {
default_random_engine e;
// seed e
a[0] = source[0];
for (int i = 1; i < n; i++) {
uniform_int_distribution<int> d(0, i);
int index = d(e);
if (index != i) {
a[i] = a[index];
}
a[index] = source[i];
}
}