我有两个数字数组,一个包含很多数字,一个只包含少数数字。数组内或数组之间没有重复:
$all = range(1, 50);
$few = array(7, 11, 19, 27, 29, 36, 40, 43);
$many = array_merge(array_diff($all, $few));
我现在想要计算每个“少数”数字之间的差异以及跟随它的所有“许多”之间的差异,但是在“少数”的下一个之前。例如,在$many
中,只有28来自$few
,介于27和29之间,所以我想计算28到27之间的差异。没有计算27的其他差异,因为没有其他{{1}从$many
开始19,我将计算差异为20,21,22,23,24,25和26,因为它们都位于19和{{1的下一个数字之间,这是27。
为了计算差异,我使用循环。这是一个稍微简化的代码(忽略了$few
中最后一个数字没有索引$few
这一事实:
[$i + 1]
如果我有庞大的数组,循环将需要很长时间才能运行。所以:
结果$few
如下所示:
$differences = array();
for($i = 0; $i < count($few); $i++) {
foreach($many as $m) {
if($m > $few[$i] && $m < $few[$i + 1]) {
$differences[] = $m - $few[$i];
}
}
}
我的基本推理是,作为一个人,我没有看到我比较的两个数组:
$differences
而是一个number line,我从一个号码到另一个号码,当我遇到一个标有“少数”的号码时,我将计算以下每个号码的所有差异,直到我遇到另一个号码“几个”:
Array $many $few
( ↓ ↓
[0] => 1 // 8 - 7 = 1
[1] => 2 // 9 - 7
[2] => 3 // 10 - 7
[3] => 1 // 12 - 11
[4] => 2
[5] => 3
[6] => 4
[7] => 5
[8] => 6
[9] => 7
[10] => 1
[11] => 2
[12] => 3
[13] => 4
[14] => 5
[15] => 6
[16] => 7
[17] => 1
[18] => 1
[19] => 2
[20] => 3
[21] => 4
[22] => 5
[23] => 6
[24] => 1
[25] => 2
[26] => 3
[27] => 1
[28] => 2
)
因为它是排序的,所以我不必遍历整个... 16 17 18 | 20 21 22 23 24 25 26 | 28 29 30 31 ...
exclude | include | exclude
19 (27)
- 来自... 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ...
... m m m f m m m m m m m f m m m m ...
↑ ↑ ... ↑
start calculate stop
的每个数字的数字编号。那么我们可以以某种方式考虑到数组是否被排序的事实?或者可能构建包含标记(“f”,“m”)和数字作为键的一个数组? E.g:
$many
答案 0 :(得分:1)
除了对sort()
的两次调用外,您只需要通过$many
进行一次循环。
// Input data provided in the question
$all = range(1, 50);
$few = array(7, 11, 19, 27, 29, 36, 40, 43);
$many = array_values(array_diff($all, $few));
// Display the values to see what we are doing
echo('$few = ['.implode(' ', $few)."]\n");
echo('$many = ['.implode(' ', $many)."]\n");
//
// The actual algorithm starts here
// Sort both $few and $many
// it works fast enough and it is required for the rest of the algorithm
sort($few);
sort($many);
// Be sure the last value of $few is larger than the last value of $many
// This is needed to avoid extra checking for the last element of $few inside the loop
if (end($few) < end($many)) {
array_push($few, end($many) + 1);
}
// Extract the first two items from $few
$current = array_shift($few);
$next = array_shift($few);
// This is the result
$differences = array();
// Run only once through $many, check each item against $next
// subtract $current from it; advance when $next was reached
foreach ($many as $item) {
// Skip the items smaller than the first element from $few
if ($item < $current) {
continue;
}
// If the next element from $few was reached then advance to the next interval
while ($next < $item) {
$current = $next;
$next = array_shift($few);
}
// Here $current < $item < $next
// This echo() is for debug purposes
echo('$current = '.$current.'; $item = '.$item.'; $next = '.$next.'; difference='.($item - $current)."\n");
// Store the difference
$differences[] = $item - $current;
}