我和好的开发者朋友进行了一次有趣的讨论。我想创建一个给定数组值的随机序列,但具有最大的碎片,没有任何可检测的模式。对于任何独特的序列,这种所谓的最大随机性实际上总是相同的。
示例输入数组:
array(1, 2, 3, 4, 5);
标准rand()函数的示例结果:
array(2, 3, 1, 5, 4);
我在上面的输出中不喜欢的是序列值,如“2,3”和“5,4”,它没有足够的碎片。
期待结果将是/可能是:
array(3, 5, 1, 4, 2);
所以我的问题; 是否有任何已知公式来计算最大随机性或更好地选择单词,最大碎片?
答案 0 :(得分:2)
那么你在说什么,而不是随机化,它是排序。随机化的结果不应该取决于初始数据的顺序。
在这种情况下,通过碎片有必要了解排序之前和之后阵列之间的差异。但必须根据任务进行不同的评估。例如,可以评估元素位置或其顺序之间的差异。
排序示例。
<?
// it must be uksort() function with sequence formula, but for me easier do like this
$array = array(1, 2, 3, 4, 5);
uk_sort($array);
function uk_sort(&$array) {
for($i=0;$i<count($array);$i++) {
if($i%2==0) {
$even[] = $array[$i];
} else {
$odd[] = $array[$i];
}
}
$even[] = array_shift($even);
rsort($odd);
$array = array_merge($even, $odd);
}
print_r($array);
?>
Array
(
[0] => 3
[1] => 5
[2] => 1
[3] => 4
[4] => 2
)
答案 1 :(得分:2)
您可以将列表拆分为两个(或更多)集合,然后将它们混合按顺序混合它们吗?
array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
array(1, 2, 3, 4, 5);
array(6, 7, 8, 9, 10);
array(2, 3, 1, 5, 4);
array(8, 7, 10, 9, 6);
array(2, 8, 3, 7, 1, 10, 5, 9, 4, 6)
这会给你一个相当高的碎片但不是最大值。 我怀疑获得最大值需要更多的工作。
答案 2 :(得分:1)
我认为这听起来像traveling salesman类型的问题,“距离”是两个选定条目之间的差异,除了你的目标是最大化总距离而不是最小化它。
我实际上对这个话题并不了解,但我认为这就是我所知道的:
有旅行商问题的算法,但它们在极限上可能非常慢(它们是NP-hard)。另一方面,有很好的近似,简单的情况可以解决,尽管它仍然是一个非平凡的算法。
根据最大碎片的重要程度,您还可以尝试一种天真的方法:给定一个元素,选择下一个元素,使其与给定元素相距很远。然后选择下一个元素,依此类推。问题在于,您的早期选择可以让您回到角落。如果碎片对你来说非常重要,那么这将不起作用。
[2,5,1,3,4] // the first three choices force us to not fragment the last two
答案 3 :(得分:1)
假设碎片被定义为连续值的绝对差值的总和,则最大碎片序列不是唯一的 - 反向序列将始终具有完全相同的碎片,并且还有更多选项,例如,所有以下排序的碎片都是11,这个数组最大:(3,1,5,2,4),(3,2,5,1,4),(2,5,1,4) ,3),(2,4,1,5,3),(4,1,5,2,3),(4,2,5,1,3),(3,5,1,4,2) ),(3,4,1,5,2)。如果还包含最后一个元素和第一个元素之间的差异,那么还有更多的对称性。
如果寻求识别特定的最大碎片序列,例如在没有明显模式的情况下,后者的概念必须形式化并进行搜索,我怀疑,从计算的角度来看,这将是昂贵的,除非目标可以形式化以便允许有效的解码。我怀疑,出于所有实际目的,一个好的启发式就足够了,例如将元素逐个插入数组(贪婪的方式),以便最大化每一步的碎片增益。
如果数组的元素不是数字,而是某些具有每对定义距离的实体,则问题确实等同于旅行商问题,正如user802500指出的那样。