对于诸如Pi之类的无穷数字,如何找到给定数字n的数字精确总和的首次出现。
例如。如果n = 20
Pi = 3.14159265358979323846264338327950950288419716939 ...
然后第一次出现是从数字1到数字5,因为: 1 + 4 + 1 + 5 + 9 = 20
如果n = 30,则第一次出现是从数字5到数字11 因为9 + 2 + 6 + 5 + 3 + 5 = 30
answer应该有一个有效的php演示
答案 0 :(得分:2)
对此的答案是使用滑动窗口来保持总和。因此,请保持两个指针分别为i
和j
。继续增加j
并在其中添加元素。当它超过期望的总和i
并减少i处的元素。然后继续增加j
,直到达到和或溢出为止,然后重复上述过程。
示例总和= 30
1
41592653589793238 >> i = j = 0 current_sum = 1
1415926
53589793238 >> i = 0 j = 6 current_sum = 28
在下一次迭代中加5将导致current_sum> 30,因此您将i递增
1 415926
53589793238 >> i = 1 j = 6 current_sum = 27
14 15926
53589793238 >> i = 2 j = 6 current_sum = 23
14 159265
3589793238 >> i = 2 j = 7 current_sum = 28
继续这种方式,它将最终到达等于sum = 30的窗口。那应该使您摆脱困境,并帮助您找到答案。
答案 1 :(得分:1)
此实现使用两个枢轴。计算$pivot_a
和$pivot_b
之间的数字总和。根据总和的值,我们增加$pivot_b
(如果总和较小)或$pivot_a
(如果总和较大)。如果总和等于$n
,请中断。枢轴的值会给出适当的数字索引。
$pi = "314159265358979323846264338327950288419716939";
$n = 30;
$pivot_a = $pivot_b = 0;
$sum = 0;
for( ; $pivot_b < strlen($pi); ) {
if($sum < $n) {
$sum += $pi[$pivot_b++];
} elseif ($sum > $n) {
$sum -= $pi[$pivot_a++];
} else {
print('Solution found from digit '.$pivot_a.' to '.$pivot_b.'.');
exit;
}
}
print('No match was found.');
此实现仅使用一个枢轴,从该枢轴开始对数字求和。如果总和恰好大于期望值,则会将总和重置为零,将枢轴移动一个位置,然后再次开始求和。
$pi = "314159265358979323846264338327950288419716939";
$n = 30;
// Let's sum up all the elements from $pivot until we get the exact sum or a
// number greater than that. In the latter case, shift the $pivot one place.
$pivot = 0;
$sum = 0;
for($k=0 ; $sum != $n && $k < strlen($pi) ; $k++) {
$sum += $pi[$k];
print($pi[$k]);
if($sum > $n) {
print(' = '.$sum.' fail, k='.($pivot+1).PHP_EOL);
$sum = 0;
$k = $pivot++;
} elseif($sum < $n) {
print("+");
}
}
print(' = '.$n.' found from digit '.$pivot.' to '.$k.'.');
实现不是很有效,但是尝试解释这些步骤。它打印
3+1+4+1+5+9+2+6 = 31 fail, k=1
1+4+1+5+9+2+6+5 = 33 fail, k=2
4+1+5+9+2+6+5 = 32 fail, k=3
1+5+9+2+6+5+3 = 31 fail, k=4
5+9+2+6+5+3 = 30 found from digit 4 to 10.
答案 2 :(得分:0)
这是另一种方法。它沿此过程建立一个求和数组,并在每次迭代时尝试将当前数字加到先前的求和上,依此类推,同时始终只保留仍然相关的和(<目标)。
函数要么返回:
null
(如果找不到目标金额)代码:
function findFirstSumOccurrenceIndexes(string $digits, int $targetSum): ?array
{
$sums = [];
for ($pos = 0, $length = strlen($digits); $pos < $length; $pos++) {
$digit = (int)$digits[$pos];
if ($digit === $targetSum) {
return [$pos, $pos];
}
foreach ($sums as $startPos => $sum) {
if ($sum + $digit === $targetSum) {
return [$startPos, $pos];
}
if ($sum + $digit < $targetSum) {
$sums[$startPos] += $digit;
}
else {
unset($sums[$startPos]);
}
}
$sums[] = $digit;
}
return null;
}