这个代码工作原理的数学解释

时间:2016-12-12 21:01:42

标签: javascript math

我在SiteFights中遇到了一个问题,我用两个循环解决了这个问题。在看其他答案的时候,我找到一个解决它没有循环,它让我张开嘴。编码器应用了Math.min / max,虽然我明白代码的作用,但我不明白为什么它有效。

我很乐意学习,因为heck,Math.max / min肯定会打败我的循环中的字节。

Given integers n, l and r, find the number of ways to represent n as a sum
of two integers A and B such that l ≤ A ≤ B ≤ r.

Example

For n = 6, l = 2 and r = 4, the output should be
countSumOfTwoRepresentations2(n, l, r) = 2.

There are just two ways to write 6 as A + B, where 2 ≤ A ≤ B ≤ 4: 6 = 2 + 4 and 6 = 3 + 3.

Input/Output

[time limit] 4000ms (js)
[input] integer n

A positive integer.

Constraints:
5 ≤ n ≤ 109.

[input] integer l

A positive integer.

Constraints:
1 ≤ l ≤ r.

[input] integer r

A positive integer.

Constraints:
l ≤ r ≤ 109,
r - l ≤ 106.

编码员的惊人答案:

function countSumOfTwoRepresentations2(n, l, r) {
    return Math.max(Math.min(Math.floor(n / 2) - l, r - Math.ceil(n / 2)) + 1, 0);
}

我的废话比较:

function countSumOfTwoRepresentations2(n, l, r) {
    var representations = 0;
    //Only travel the loop until n/2 , because l+r will never equal n
    // if l or r > n/2
    var limit = Math.floor(n/2);
    for(var i=l; i<=r && i<=limit; ++i){
        for(var j=i;j<=r;++j){ 
            if(i+j == n){
                ++representations;
                break; 
            }
        }
    }
    return representations;
}

1 个答案:

答案 0 :(得分:3)

  

给定整数nlr,找出将n表示为两个整数AB的总和的方法的数量,以便l ≤ A ≤ B ≤ r

首先,考虑如果n是偶数并让x = n/2,我们至少有一个解决方案(x + x),当且仅当l ≤ x ≤ r时。如果x不在该范围内,那么就没有解决方案,因为x < ll + l > nr < xr + r < n

可以推广到偶数或奇数n:如果且仅限于l ≤ floor(x) ≤ ceil(x) ≤ r,则有一个解决方案。如果我们允许A = floor(x)B = ceil(x),则该解决方案为A + B。通过在每个方向上从该点开始沿着数字线迈出一步,可以找到所有其他解决方案。 (A - 1) + (B + 1) = A + B = n,因此只要(A - 1) + (B + 1)没有越过(A - 1)边界且l没有越过(B + 1)r就是一个解决方案{1}}边界。所以,如果你想要一个只有一个循环的解决方案,你可以这样做:

function countSumOfTwoRepresentations2(n, l, r) {
    var x = n/2;
    var A = Math.floor( x );
    var B = Math.ceil( x );
    for ( var count = 0; l <= A && B <= r; count++) {
        A--;
        B++;
    }
    return count;
}

但该循环重复多少次?好吧,它会迭代,直到其中一个停止条件发生:

  1. A小于l
  2. B变得大于r
  3. 如果1.首先发生,那么它会迭代Math.floor( x ) - l + 1次,而如果先发生2.,它会迭代r - Math.ceil( x ) + 1(如果两个条件都发生在同一次迭代中,那么{ {1}})。

    只要有一个解决方案,循环就会迭代较小的Math.floor( x ) - l === r - Math.ceil( x )Math.floor( x ) - l + 1次,这就是编码器得到答案r - Math.ceil( x ) + 1的地方(在替换{{1}之后) }返回Math.min(Math.floor(n / 2) - l, r - Math.ceil(n / 2)) + 1并将x拉出每个字词并在之后添加。

    如果没有解决方案,n/2,该公式会给出否定结果,但应该提供+ 1,这就是他添加EG. n = 10, l = 20, r = 20的原因。

    为清楚起见,编码器的解决方案可以写成(仍然没有循环):

    0