c# - 随机排列元素,使得任何元素都不应出现在其原始索引处

标签 c# algorithm random permutation shuffle

我有一个对象元素列表

SourceList    ResultList (Expected)

Obj_A                 Obj_F

Obj_B                 Obj_C

Obj_C                 Obj_G

Obj_D                 Obj_B

Obj_E                 Obj_A

Obj_F                 Obj_B

Obj_G                 Obj_E

随机播放 SourceList 中的元素,这样,任何元素都不应出现在其原始索引处(在 SourceList 中)在 ResultList 中。

例如,在 SourceList 中,C 在索引 2 处,因此它不能出现在 ResultList 中的索引 2 处强>

到目前为止,我已经调查了Dearrangement Wiki ,但算法给了我可能的安排,我只需要一个。

最佳答案

您可以使用 fisher-yates shuffle作为一个黑盒子,重复打乱你的数组,直到你的结果是一个重新排列。

伪代码:

while true:
     arr = [1,2,...,n]
     shuffle(arr)
     flag = true
     for i from 0 to n:
        if arr[i] == i: //not a dearrangement
           flag = false 
     if flag == true: //it's a dearrangement
        break

shuffle(arr): //fisher yates
    for i from 0 to n:
       j = rand(i,n)
       swap(arr,i,j)

这种方法的特性:

  • 这保证是统一且无偏的,因为每个有效的重新排列 在每次迭代中获得完全相同的选择几率。
  • 由于 Fisher-Yates 生成所有排列,而我们仅使重新排列无效 - 每个重新排列都是可实现的
  • 获得重新排列的概率是 1/e1,这意味着在平均情况下您将需要 (1-1/e)^-1 ~=1.56 次洗牌,这意味着此算法以O(n) 预期时间复杂度 运行。

(1) The number of dearrangementsint(n!/e + 1/2),这意味着一个数组被重新排列的概率是(n!/e + 1/2)/n! ~= 1/e,对于较大的 n 值。

关于c# - 随机排列元素,使得任何元素都不应出现在其原始索引处,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28738633/

相关文章:

c# - 在 C# 中读取选中哪个 RadioButton 的正确方法是什么?

c# - 列出有向图中的所有负循环

c - 使用异或在数组中重复和缺失的数字

java - DFS 一棵没有内存的树

Python 3 操作系统.urandom

java - 如何使用特定字符生成特定长度的随机字符数组

C# 等效于 C++ GDI 代码

c# - 在 Windows 64 位下设计 C# 应用程序是一个好习惯吗?

c# - Paypal 订阅按钮错误

javascript - 如何在不使用 Math.random() 函数的情况下使用 JavaScript 创建随机数生成器函数?