for (var x = 0; x < 10; x++) {\n if (x % 3 === 0 || x % 5 === 0) {\n console.log(x)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这会打印出:0,3,5,6,9。我想要一个输出\xe2\x80\x94总和,或23\xe2\x80\x94并打印一次console.log,而不是单独打印每个术语。
我怎样才能找到这个序列的总和?
\n循环固然很好,但这个问题实际上只是数学问题。我们可以做得更好,在常数时间内求和。
等差数列是指项之间的差恒定时的数列。例如,
1, 2, 3, 4, 5...
Run Code Online (Sandbox Code Playgroud)
是一个算术数列d,其中项之间的差为 1。
0, 2, 4, 6, 8...
Run Code Online (Sandbox Code Playgroud)
是ad为2的算术数列。
如果我们看一下我们的序列:
0, 3, 5, 6, 9...
Run Code Online (Sandbox Code Playgroud)
我们很快就能看到有两个重叠的算术序列(3n和5n):
0, 5, 10, 15... and 0, 3, 6, 9, 12, 15...
Run Code Online (Sandbox Code Playgroud)
然后我们可以很快看到共享项是 15 的倍数。
求总和比看起来容易。我们可以使用有史以来最伟大的数学家之一卡尔·弗里德里希·高斯(Karl Friedrich Gauss)在很小的时候就凭直觉(但没有发现)的方法(iirc,6 岁)。
让我们再看看我们的3n序列:
0, 3, 6, 9, 12, 15...
Run Code Online (Sandbox Code Playgroud)
你看到一个模式了吗?如果我们抽对,从每一端取一个数字......
0 and 15
3 and 12
6 and 9
Run Code Online (Sandbox Code Playgroud)
我们最终得到常数和 15。由此,我们可以得出一个公式。
有多少对?n / 2,其中n是项数。
每对的总和是多少?a1 + aN,其中a1是第一项,aN是最后一项。
这意味着我们的总和是
S = (n / 2) * (a1 + aN)
Run Code Online (Sandbox Code Playgroud)
我们快到了。如果我们将两个序列的和相加,我们会得到一点额外的结果。为什么?
0, 3, 6, 9, 12, 15...
0, 5, 10, 15...
Run Code Online (Sandbox Code Playgroud)
我们数15的倍数两次!但这很容易解释:
grandTotal = sum3 + sum5 - sum15
Run Code Online (Sandbox Code Playgroud)
我们的解决方案(您可能更感兴趣arithmeticProgression):
/*
finds the sum of two arithmetic sequences, on [min, max] (inclusive)
for two numbers a and b
*/
function getSum (min, max, a, b) {
function arithmeticProgression (start, stop, m) {
// find the nearest multiple of m greater than or equal to the starting bound
start = m * Math.ceil(start / m)
// find the nearest multiple of m less than or equal to the ending bound
stop = m * Math.floor(stop / m)
// the number of terms, e.g., in 0, 2, 4, 6, 8
// we have 5 terms because of (max - min)/delta + 1
// or, ((8 - 0) / 2) + 1 = 4 + 1 = 5
var terms = ((stop - start) / m) + 1
// our formula from before
return (terms / 2) * (start + stop)
}
var sum3 = arithmeticProgression(min, max, a)
var sum5 = arithmeticProgression(min, max, b)
var sum15 = arithmeticProgression(min, max, a * b)
return sum3 + sum5 - sum15
}
Run Code Online (Sandbox Code Playgroud)
测试:
console.log(getSum(0, 9, 3, 5) === 23) // true
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8121 次 |
| 最近记录: |