我有两个列表(lista和listb),每个列表包含一个未知数量的点(结构中有两个整数)。
我想创建一个包含lista和listb中唯一随机配对的新列表。所以一个示例条目可能是[12,14],其中12是lista的索引,14是listb的索引。
我还想在调用此函数时设置最大配对数。因此,不是将lista中的每个元素与listb中的每个元素配对,而是将其限制为200个随机配对作为示例。
我的第一次尝试是简单地生成所有可能的配对。随机播放列表并将任何元素都删掉。这个解决方案几乎没有足够的效率。
我的下一个尝试是为每个可能索引的每个原始列表创建一个数组,将它们分开进行洗牌,然后迭代它们直到我有最大数量的配对(或所有这些配对)。这有几个问题,我不确定如何解决。其中之一,lista可以拥有1000万个元素供我所知。创建一个包含1000万个元素的新数组(索引列表)并在我的最大对可能只有200时进行混洗?到目前为止似乎很傻。
我考虑过从lista / listb中选择随机元素,看看我是否已经将它们配对,然后再将它们添加到新列表中。这也是一个非常愚蠢的选择,因为可以花很多时间一遍又一遍地选择重复配对。
那么,这里有什么好选择还是有选择呢?我不想迭代每个可能的组合,配对需要是唯一的,从列表中删除选项是非常慢的,因为当它们非常大时阵列重新调整大小,在选择中分布需要非常均匀每个清单的过程等。
感谢您的帮助。
编辑 - 我的意思是关于对子本身的独特方面。因此,只要listb中的元素每次都不同,lista中的元素10就可以反复使用。唯一的问题是我不想立即限制lista和listb,因为我需要在每个配对的两个列表中进行相当均匀的分配。
答案 0 :(得分:1)
数学或统计数据buff可能会为您提供一个评估此公式的公式,但我只是编写了一些测试代码。
代码只是选择随机对,每次看到重复时它都会再次尝试。然后对于每个这样的“选择随机对直到唯一”循环,它计算它做了多少重试并跟踪它。最后,这总结为一个全局数组来跟踪这些事物的相对频率。
这是执行约1分钟后的结果:
84382319 81 0 0 0 0 0 0 0 0
这些数字意味着:
所以,显然如果你增加你想要产生的对数或者减少选择错误的数字,这将开始上升,但我不确定这会在实践中造成问题。
这是我使用的LINQPad程序:
static Random R = new Random();
void Main()
{
var a = 10000;
var b = 10000;
var n = 200;
int[] counts = new int[10];
var dc = new DumpContainer().Dump();
while (true)
{
var once = Test(a, b, n);
for (int i = 0; i < once.Length; i++)
counts[i] += once[i];
dc.Content = Util.HorizontalRun(true, counts);
}
}
public static int[] Test(int a, int b, int n)
{
var seen = new HashSet<Tuple<int, int>>();
var result = new int[10];
for (int index = 0; index < n; index++)
{
int tries = 0;
while (true)
{
var av = R.Next(a);
var bv = R.Next(a);
var t = Tuple.Create(av, bv);
if (seen.Contains(t))
tries++;
else
{
seen.Add(t);
break;
}
}
result[tries]++;
}
return result;
}
答案 1 :(得分:1)
为避免完全重复,您可以尝试执行稀疏 Fisher-Yates shuffle。
Dictionary<int, int> dict
,它将映射Fisher-Yates数组中没有自己索引的&#34;索引&#34;到&#34;该指数的值&#34;。n
项,请从x
(包括)中选择一个随机数n
到&#34; ListA的大小&ListB的大小&#34; (独家)
dict[x] ?? x
是您的所选项目。dict[n] ?? n
存储在dict[x]
。