我有一个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,但算法给了我可能的安排,我只需要一个。
答案 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)
此方法的属性:
O(n)
预期时间复杂度运行。(1)The number of dearrangements为int(n!/e + 1/2)
,这意味着对于(n!/e + 1/2)/n! ~= 1/e
的较大值,数组为重排的概率为n
。