diff --git a/Maths/Factors.js b/Maths/Factors.js index 68bbde6d23..9bfc46f06b 100644 --- a/Maths/Factors.js +++ b/Maths/Factors.js @@ -7,10 +7,30 @@ * */ +/** + * Finds every positive factor of a number in ascending order. + * + * Time complexity: O(sqrt(number)) + * Space complexity: O(k), where k is the number of factors + */ const factorsOfANumber = (number = 0) => { - return Array.from(Array(number + 1).keys()).filter( - (num) => number % num === 0 - ) + if (!Number.isInteger(number) || number <= 0) return [] + + const lowerFactors = [] + const upperFactors = [] + + for (let divisor = 1; divisor <= number / divisor; divisor++) { + if (number % divisor !== 0) continue + + lowerFactors.push(divisor) + + const pairedDivisor = number / divisor + if (pairedDivisor !== divisor) { + upperFactors.push(pairedDivisor) + } + } + + return lowerFactors.concat(upperFactors.reverse()) } export { factorsOfANumber } diff --git a/Maths/test/Factors.test.js b/Maths/test/Factors.test.js index 1ad60132d3..9f2d8cde4a 100644 --- a/Maths/test/Factors.test.js +++ b/Maths/test/Factors.test.js @@ -1,10 +1,19 @@ import { factorsOfANumber } from '../Factors' describe('Factors', () => { - factorsOfANumber(50).forEach((num) => { - it(`${num} is a factor of 50`, () => { - const isFactor = 50 % num === 0 - expect(isFactor).toBeTruthy() - }) + it.each([ + [1, [1]], + [16, [1, 2, 4, 8, 16]], + [50, [1, 2, 5, 10, 25, 50]], + [97, [1, 97]] + ])('returns every factor of %i in ascending order', (number, expected) => { + expect(factorsOfANumber(number)).toEqual(expected) }) + + it.each([0, -1, 1.5])( + 'returns an empty array for invalid input %s', + (number) => { + expect(factorsOfANumber(number)).toEqual([]) + } + ) })