一年前,我在R论坛中询问了a question关于如何置换序列1000次但从不允许重复元素的问题。现在仍然如此,R中的任何解决方案对我的需求来说都太慢了。
问题是这样的:
对于每个字母都是单独元素的序列,例如
"...IDPGCGDCIDPGCGCDIDPGCGDCPGCIDPFJAIAHAHAHABAHAHABKPGCPGCGCECDGCPGCGCIDIPFCPGEPAJIAEPGCECJIPGCGPGCGCGADPDJDPGCPCPGCDIPEPGCJAJMAHZABAHAHAHABHAHBKRZALOBKAHABKLAHAHAHABKLKLAKLBKABABLAHAHABKBKLOKIABKLAHAHABKLABKALKABKLKAHBAKLABKBAHABLALKABABJLKAKLKHABKCRAHAKLKAKLABKLKLBKAHAKLKECECGDCGECGEDGCDGDGECECEGDCACACAHABABCDCHAHBKCQGCGCQCQGCQCGCACACBKCDCAHACQGCPGCDACAPCQAHAHBKACHAHAHBABCGCGCAHAHAMHMABAHAKLABKCPCFCABCQCQGCGCABHAHANBKQAHAHANANABKLABAKLPCGCGCPCAHABAHAHAHAHANBKALCQCGCECAHABANAHBKAKBKAHABAHBKALBHAHABKLKCPCECALCGCAKPHBAHAHAHAHAHAHABAHAHBKAMJABAHBAHAHBKALKABKPCQBANAHANHABKHBALAHALAHANBANBHABKAHANHAHABKAHAHAHAHAMANIAHABANHABABKBKLHLKLBKLKBKBKBALAHAKLBKLBHKBABHAMABKZAHAHABLKAHABAKABKOKHAKAHAHBKAHAHAHABKLHAHBKAHABKLAHAHABKAIAIAHABKLBAIAIKLKLAHAH..."
我需要对这个序列进行10000次置换(随机混洗)。原始序列永远不会有任何重复的元素。随机采样序列需要具有与原始序列相同比例的元素,但也没有重复元素。序列长度可达50,000个元素。每个元素的总数看起来像这样:
A B C D E F G H I J K L M N O P Q R Z
6537 3156 1736 198 445 138 1129 3849 818 287 2339 1190 275 1035 222 484 242 338 59
我尝试使用R
来解决此问题。尝试的一切都太慢了,也不是很擅长找到不重复的元素。我不了解C++
那么好,但有兴趣尝试通过Rcpp
来使用它来获得有效的解决方案。
我认为这将是一个有趣的问题,并且在允许的情况下会为它添加赏金。
长序列示例为available here。
答案 0 :(得分:1)
一种方法是通过在随机位置添加新元素来构建序列中的一个元素,而不是按顺序选择每个元素。
使用以下算法:
a
。b
开头。e
中的每个元素a
:
attempts
设为零attempts
< max_attempts
:
p
到0
选择一个随机位置b.size()
,其中0表示第一个元素,b.size()
表示最后一个元素,并检查是否可能在此位置插入e
而不会导致重复。如果可能,请将e
插入位置b
的{{1}},否则请增加p
然后重试attempts
次尝试中未插入任何元素,请从头开始重新开始我无法证明这会产生均匀分布,但我认为它将不受任何偏差的影响,这些偏差将某些元素聚集到序列的开始或结束,其中使用顺序方法可以更加确定可能性。它可能会失败(例如,如果要为插入的第一个和第二个元素选择相同的元素),但这是便宜的,而max_attempts
很短并且变得越来越不可能(假设频率分布类似于你告诉我们的一个)。 OTOH,你很容易想出会导致它失败的病态分布(例如10000 As和10000 Bs,没有其他字母)。
这可以使用列表b
的stl列表和引用列表中每个元素的迭代器数组在C ++中以线性时间实现。添加新元素时,将指向该元素的迭代器添加到数组的末尾。要在列表中选择随机位置,请从数组中随机选择一个迭代器。