在给定范围内生成符合我具体标准的非重复整数序列需要做些什么?
以下是标准:
例如:
SET: 1,2,3,4,5,6,7,8,9
随机序列(带重复):
2,4,6,9,3,1,5,2,8,7,3
r, , , ,r, , ,x, , ,x
这里我已经指出了随机选择的数字(随机序列中的前5个)和r
以及它们随机放置的插入点(进入最后5个)最终序列)x
。
非常感谢任何帮助解决这个问题。实际使用会比这更复杂,但我知道一旦我能做到这一点我将需要做什么。
修改
为了澄清一点,我有1-20,我需要一个22位的随机序列。必须使用每个号码,两个将使用我原来的帖子中讨论的两次。我选择了10以上简化了一点。我应该能够适应你所有的逻辑。
答案 0 :(得分:0)
我假设当你说"非重复"你是说" distinct" (独特的)而不是"最终成为周期性的#34; (如" pi的数字不重复")
不需要删除子列表,但可以更容易地进行概念化。
如果n + 2小于10,该怎么做并不明显。特别是,该算法可能会因n< 5并返回错误的结果n = 7。
答案 1 :(得分:0)
要在范围内生成不同的数字,您可以使用以下内容:
$arr_num = array();
while(count($arr_num)<=7)
{
$num = rand(1, 9);
if (!in_array($num, $arr_num))
{
$arr_num[] = $num;
}
}
$ arr_num现在有8个不同的元素。选择数组的五个元素:
for ($i=0; $i<=4; $i+=1)
{
$new_arr[$i] = $arr_num[$i];
}
现在从$ new_arr数字中选择两个数字:
$r1 = array_rand($new_arr);
$r2 = array_rand($new_arr);
现在,您可以在最后一个随机位置的两个位置将这些数字插入原始数组中。希望它有所帮助!
答案 2 :(得分:0)
如果我理解正确,你有1到N个随机数,必须在10组排列中使用,并且有一些关于重复的特定标准。在PHP中,我建议这(不计算php-internals)O(n)解决方案:
//Generate a full list of keys
$source = range(1, MAX);
//NOTE: if MAX < 10, you must pad the array
//Get a random group of 10 of the keys
$input = array_rand(array_flip($source), 10);
//Shuffle (can be done later as well; this is the randomization).
//array_rand() does not change order.
shuffle($input);
//Select the first of 5 that must be repeated in the last 5
$one = rand(0, 4);
$onev = $input[$one];
//Remove this array key to prevent collisions with the second of 5
$input = array_diff($input, array($onev));
//Select a random index in the last 5 to be replaced with $one
$rep = rand(5, 9);
$repv = $input[$rep];
//Remove this array key to prevent collisions with the other to-be-replaced
$input = array_diff($input, array($repv));
//Acquire the new keys list of input now that two elements have been removed
$keys = array_slice(array_keys($input), 0, 3);
//Select the second-of-5 to replace in the last 5. No worry of collision now.
$two = array_rand($keys, 1);
$two = $keys[$two];
//Select the second from the last-of-5 to be replaced by $two
//No worry of collision because the other index is removed.
$keys = array_slice(array_keys($input), 4, 8);
$rept = array_rand($keys, 1);
$rept = $keys[$rept];
//Replace one of the last-of-five with one of the first-of-five
$input[$rept] = $input[$two];
//Restore removed keys as well as perform replacement of other last-of-five
$input[$one] = $onev;
$input[$rep] = $onev;
//re-randomize based on shuffle
ksort($input);
没有循环,没有条件。
答案 3 :(得分:0)
$max = 15;
$array = array(1, $max);
for($x = 1; $x <= $max; $x++)
{ $array[$x] = rand(1, $max); }
$firstDup = $array[rand(1,5)];
$secondDup = $firstDup;
do { $firstDup = $array[rand(1,5)];
} while($firstDup == $secondDup);
do { $array[rand($max-5,$max)] = $firstDup;
} while(!in_array($firstDup,array_slice($array,$max-5,5)));
do { $array[rand($max-5,$max)] = $secondDup;
} while(!in_array($secondDup,array_slice($array,$max-5,5)));
答案 4 :(得分:0)
希望这能让你顺利开始:
$max = 20; // max value
$repeats = 2; // numbers to be repeated
$nums = range(1, $max);
shuffle($nums);
$halfPoint = ceil($max / 2);
$firstHalf = array_slice($nums, 0, $halfPoint);
$repeaters = array_intersect_key($firstHalf, array_flip(array_rand($firstHalf, $repeats)));
$secondHalf = array_merge(array_slice($nums, $halfPoint), $repeaters);
shuffle($secondHalf);
$result = array_merge($firstHalf, $secondHalf);
var_dump(join(',', $result));
答案 5 :(得分:0)
对此解决方案发出警告。我不会将它用于大量数字。如果我为更大的集合做同样的解决方案,我会使用array_splice从数组中删除选定的成员。当您获得更大的空间时,在您的范围内找到未使用的数字会变得非常昂贵,并且需要比下面的强力方法更好的解决方案。
这将构建目标集的一半。你会打两次,每半个一次。
function build_half($min, $max, $num_elements, $arr = array() ){
while( count($arr) <= $num_elements)
{
$candidate = rand($min, $max);
if( !in_array($candidate, $arr))
{
array_push($arr, $candidate);
}
}
return $arr;
}
这将从数组中获取$ this_many元素。
function random_grab($arr, $this_many){ // don't try this on the subway
$nums_to_repeat = array();
// catch some edge cases...
if( $this_many > count($arr) )
{
return FALSE;
}
else if( $this_many == count($arr) )
{
return shuffle($arr);
}
while( count($nums_to_repeat) <= $this_many)
{
$rand_key = rand(0, count($arr) - 1);
if( ! in_array($arr[$rand_key], $nums_to_repeat))
{
array_push($nums_to_repeat, $arr[$rand_key]);
}
}
return $nums_to_repeat;
}
这是一个相当专业的案例,但可以通过允许偏移楼层和天花板作为参数传递而更加通用。对于你的问题,他们将是5和9,所以我们直接派生他们。
function random_insert_2nd_half($target, $source){
$offsets_consumed = array();
$num_elements = count($target);
while( count($source) > 0 )
{
$offset = rand( ($num_elements/2), $num_elements - 1);
if( ! in_array( $offset, $offsets_consumed)
{
$arr[$offset] = array_pop($nums_to_repeat);
}
}
}
好的,完成所有这些之后,让我们把它付诸实践。
// Generate the first half of the array
$my_array = $repeated_nums = array();
$my_array = build_half(1, 10, 5);
// then grab the 2 random numbers from that first half.
$repeated_nums = random_grab($my_array, 2);
// So now we have our random numbers and can build the 2nd half of the array.
// we'll just repeat the call to the first function.
$my_array = build_half(1, 10, 5, $my_array);
// Then swap out two of the values in the second half.
$my_array = random_insert_2nd_half($my_array, $repeated_nums);
// at this point $my_array should match what you are looking for.