SPOILER ALERT. Working solution here. Don’t look in code if you wanna do it on your own.
Using some cool trick for dealing with nested loops. Such hint was kindly given to me in this thread
Wondering maybe I can optimize this code even more? No ideas for now.
function sumSquareDifference(n) {
//assume have case >>> n = 3
//sum of the squares >>> 1^2 + 2^2 + 3^2
//square of the sums >>> 1^2 + 2^2 + 3^2 + 2(1 * 2) + 2 (1 * 3) + 2 * (2 * 3)
//difference is obvious
//need to find sum of products of pair combos of numbers from 1 to n
//then multiply it by 2
let result = 0;
for (let i = 1; i <= n; i++) {
//inner loop optimized >> to avoid duplicates
//>>to avoid squares like (1 * 1)
//to reduce loop steps (bigO better than O(n^2) here)
for (let j = i + 1; j <= n; j++) {
result += i * j;
}
}
return 2 * result;
}
sumSquareDifference(100);
When you answered, I was in the middle of some coding experiment, so I coded this: note: not sure how can I call it? test function/ research function…?
Not sure if it is useful at all tho
//compare number of iterations
const countNumberOfIterations = (minSize, maxSize, step) => {
//will print comparison for each problem size rom 1 to n
for (let problemSize = minSize; problemSize <= maxSize; problemSize += step) {
let countClassic = 0;
let countJequalI = 0;
for (let i = 0; i < problemSize; i++) {
for (let j = 0; j < problemSize; j++) {
countClassic++;
}
}
for (let i = 0; i < problemSize; i++) {
for (let j = i; j < problemSize; j++) {
countJequalI++;
}
}
console.log('For the problemsize ' ,problemSize);
console.log('Classic loops do ', countClassic, ' iterations.')
console.log('J equal I situation gives ', countJequalI, ' iterations.');
console.log('Relative complexity(classic to jequali)', countClassic/countJequalI)
console.log('-----------------')
}
}
countNumberOfIterations(10, 100, 10);
/*
For the problemsize 10
Classic loops do 100 iterations.
J equal I situation gives 55 iterations.
Relative complexity(classic to jequali) 1.8181818181818181
-----------------
For the problemsize 20
Classic loops do 400 iterations.
J equal I situation gives 210 iterations.
Relative complexity(classic to jequali) 1.9047619047619047
-----------------
For the problemsize 30
Classic loops do 900 iterations.
J equal I situation gives 465 iterations.
Relative complexity(classic to jequali) 1.935483870967742
-----------------
For the problemsize 40
Classic loops do 1600 iterations.
J equal I situation gives 820 iterations.
Relative complexity(classic to jequali) 1.951219512195122
-----------------
For the problemsize 50
Classic loops do 2500 iterations.
J equal I situation gives 1275 iterations.
Relative complexity(classic to jequali) 1.9607843137254901
-----------------
For the problemsize 60
Classic loops do 3600 iterations.
J equal I situation gives 1830 iterations.
Relative complexity(classic to jequali) 1.9672131147540983
-----------------
For the problemsize 70
Classic loops do 4900 iterations.
J equal I situation gives 2485 iterations.
Relative complexity(classic to jequali) 1.971830985915493
-----------------
For the problemsize 80
Classic loops do 6400 iterations.
J equal I situation gives 3240 iterations.
Relative complexity(classic to jequali) 1.9753086419753085
-----------------
For the problemsize 90
Classic loops do 8100 iterations.
J equal I situation gives 4095 iterations.
Relative complexity(classic to jequali) 1.978021978021978
-----------------
For the problemsize 100
Classic loops do 10000 iterations.
J equal I situation gives 5050 iterations.
Relative complexity(classic to jequali) 1.9801980198019802
-----------------
*/
Big O complexity is a very crude metric. Big O talks about how the amount of work scales as n gets massive. In this case, a double nested loop does kn^2 operations while your modified double nested loop has k/2n^2 operations. You saw that factor of 2 in your experiments. That’s the same complexity class in each approach. Big O does not care about the factor of two.
That said, the algorithm you wrote requires you to cut out these extra iterations for correctness. You should always do exactly as many loop iterations as you need. No more or less.
It is important to remember that Big O is only one tool in writing good code.
There exists a O(1) solution to this problem.
Polynomial time loop fusion is something a compiler would do. I don’t think most JS engines would do it. In any case, O(n^2) is polynomial complexity already.
So there is just some simple formula for that somewhere? And inside function will be one line of code basically?
I’ve heard that some euler problems can be solved with pencil/paper tools.
EDIT. I guess I found that on fCC page with solution.
By the way, on the page with solution to this problem some strange stuff is going on.
In explanation of the problem there are blank lines where formulas should be.
Followed up question(to make sure):
O(n^2) and O(n^3) >>> this is one class of complexity? Can I say that it’s all one class of complexity, which is O(n^c)?
And different class of complexity would be, for example O(c^n)?