随机元素使得没有元素应该在其原始索引处

时间:2015-02-26 09:27:26

标签: c# algorithm random permutation shuffle

我有一个Object元素列表

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,但算法给了我可能的安排,我只需要一个。

3 个答案:

答案 0 :(得分:1)

进行随机播放,并获取所有索引未更改的元素,然后为所有这些错误的元素旋转位置。

答案 1 :(得分:1)

这对我有用:

var SourceList = new List<string>()
{
    "Obj_A", "Obj_B", "Obj_C", "Obj_D", "Obj_E", "Obj_F", "Obj_G",
}; 

var rnd = new Random();

var ResultList =
    Enumerable
        // create an exceedingly long sequence for retries
        .Repeat(0, int.MaxValue)
        // select and randomly order all of the indices of `SourceList`
        .Select(_ => Enumerable.Range(0, SourceList.Count)
            .OrderBy(x => rnd.Next())
            .ToArray())
        // Discard the indices if they have any matching positions
        .Where(x => !x.Where((y, i) => y == i).Any())
        // only take one successful set of indices
        .Take(1)
        // flatten the list of lists to a list
        .SelectMany(x => x)
        // select the elements from `SourceList` from their index positions
        .Select(x => SourceList[x])
        // convert to list
        .ToList();

使用.OrderBy(x => rnd.Next())会产生统一的排序(没有偏见) - 我在过去已经证实了这一点。

答案 2 :(得分:1)

您可以使用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 / e 1 ,这意味着你需要(1-1 / e)^ - 1~ = 1.56 shuffles在平均情况下,这意味着此算法以 O(n)预期时间复杂度运行。

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