Reputation: 3
I am trying to programme a function that takes a non-negative integer, and returns a list of non-negative integer pairs whose values - when squared - sum to the given integer.
examples:
5 --> [ [1, 2] ]
25 --> [ [0, 5], [3, 4] ]
325 --> [ [1, 18], [6, 17], [10, 15] ]
My solution works in an IDE but when I submit it to codewars I receive exit code error 139: FATAL ERROR: invalid table size Allocation failed - JavaScript heap out of memory. The codewars documentation indicates that this is due to an inefficient algorythm.
Initially my solution contained a nested loop which was causing long run time but I have since refactored my code to remove this. Despite this reduced complexity I still get the same error.
Any suggestions how I can further decrease the complexity?
const allSquaredPairs = (n) => {
//get array of all numbers between 0 and sqrt of n
let possibleNums = Array(n)
.fill()
.map((_, i) => {
if ((i + 1) ** 2 <= n) return i + 1; //only numbers lesser than sqrt of n
})
.filter(n => n!=undefined)
possibleNums = [0, ...possibleNums];
const matchingPairs = [];
while (possibleNums.length){
const num1 = possibleNums[0];
const num2 = possibleNums[possibleNums.length-1];
const sum = num1 ** 2 + num2 ** 2
if (sum === n) matchingPairs.push([num1, num2]);
if (sum > n ) possibleNums.pop()
else possibleNums.shift()
}
return matchingPairs;
};
console.log(allSquaredPairs(25));
Upvotes: 0
Views: 77
Reputation: 4198
Your solution allocates an array of length n, and then iterates over it. That means that the memory requirement for your solution increases linearly as n increases.
You could implement this without allocating that array so that the memory requirement is constant no matter how large the value of n.
const examples = [
{ input: 5, output: [ [1, 2] ] },
{ input: 25, output: [ [0, 5], [3, 4] ] },
{ input: 325, output: [ [1, 18], [6, 17], [10, 15] ] },
{ input: Number.MAX_SAFE_INTEGER, output: [] }
];
function allSquaredPairs(n) {
const matchingPairs = [];
const smallestIntegerLargerThanSquareRootOfN = Math.ceil(Math.sqrt(n));
let lowerBound = 0;
let upperBound = smallestIntegerLargerThanSquareRootOfN;
while (lowerBound < upperBound) {
const sum = lowerBound ** 2 + upperBound ** 2;
if (sum === n) {
matchingPairs.push([lowerBound, upperBound]);
lowerBound += 1;
} else if (sum < n) lowerBound += 1;
else if (sum > n) upperBound -= 1;
else console.log("ERROR!")
}
return matchingPairs;
}
examples.forEach(({ input, output}) => console.log({ n: input, expected: JSON.stringify(output), " actual": JSON.stringify(allSquaredPairs(input)) }));
As a point of interest, I tried this with let whatever = new Array(n)
at the start of the function, and for the max safe integer test case it threw RangeError: invalid array length
. That's a different error than you were seeing, but it does illustrate how allocating an array of length n
can complicate things.
Upvotes: 2