I encountered a problem in the site CodeFights that I resolved with two loops. While looking at other answer I found one that resolved it with no loops and it left me with my mouth open. The coder applied Math.min/max , and while I do understand what the code does I don't understand why it works.
I've love to learn because heck, Math.max/min beats the bytes out of my loops for sure.
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.
The coder's amazing answer:
function countSumOfTwoRepresentations2(n, l, r) {
return Math.max(Math.min(Math.floor(n / 2) - l, r - Math.ceil(n / 2)) + 1, 0);
}
My crap in comparison:
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;
}
Given integers
n
,l
andr
, find the number of ways to represent n as a sum of two integersA
andB
such thatl ≤ A ≤ B ≤ r
.
First, consider that if n
is even and letting x = n/2
, we have at least one solution ( x + x
) if, and only if, l ≤ x ≤ r
. If x
isn't in that range then there is no solution, since either x < l
and l + l > n
or r < x
and r + r < n
.
That can be generalized to even or odd n
: There is a solution if, and only, if: l ≤ floor(x) ≤ ceil(x) ≤ r
. If we let A = floor(x)
and B = ceil(x)
, that solution is A + B
. Every other solution can be found by taking one step along the number line away from that point in each direction. (A - 1) + (B + 1) = A + B = n
, therefore (A - 1) + (B + 1)
is a solution as long as (A - 1)
hasn't crossed the l
boundary and (B + 1)
hasn't crossed the r
boundary. So, if you wanted a solution with only one loop, you could do something like this:
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;
}
But how many times does that loop iterate? Well, it iterates until one of the stopping conditions happens:
A
becomes smaller than l
B
becomes larger than r
If 1.
happens first, then it iterates Math.floor( x ) - l + 1
times, whereas if 2.
happens first it iterates r - Math.ceil( x ) + 1
(if both conditions happen on the same iteration, then Math.floor( x ) - l === r - Math.ceil( x )
).
As long as there is a solution the loop iterates the smaller of Math.floor( x ) - l + 1
or r - Math.ceil( x ) + 1
times, which is where the coder got the answer Math.min(Math.floor(n / 2) - l, r - Math.ceil(n / 2)) + 1
from (after substituting x
back for n/2
and pulling the + 1
out of each term and adding it after instead.
If there is no solution, EG. n = 10, l = 20, r = 20
EG. n = 10, l = 20, r = 20
, that formula will give a negative result, but it should give 0
instead, which is why he added Math.max( result, 0 );
.
For clarity, the coder's solution could be written as (still with no loops):
function countSumOfTwoRepresentations2(n, l, r) {
var x = n/2;
var A = Math.floor( x );
var B = Math.ceil( x );
// Every solution is of the form (A - i) + (B + i), where i is an integer >= 0
// How many values of i are valid for l <= (A - i)
var stepsA = A - l + 1;
// How many values of i are valid for (B + i) <= r
var stepsB = r - B + 1;
// If the formulas gave a negative amount of valid steps,
// there is no solution, so return 0
if ( stepsA < 0 || stepsB < 0 )
return 0;
// Otherwise, return the smaller valid amount of steps,
// that is the number of steps that are valid for both A and B
return Math.min(stepsA, stepsB);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.