Это немного сложнее.Во-первых, пожалуйста, исправьте ошибку в вашем коде, она должна быть i <= Math.sqrt(n);
вместо i < Math.sqrt(n);
.
Давайте начнем с уникального представления целого числа как произведения степеней его простых делителей:
n = p 1 a 1 p 2 a 2 p 3 a 3 ... p k a k
(например, 120 = 2 3 3 1 5 1 ).Сколько раз цикл for
в вашем коде будет выполняться для ввода n
(не считая рекурсивных под-вызовов)?Точно i-1
раз, где i
- наименьший простой делитель n
.Это потому, что когда первый такой i
найден, цикл завершается (оператор return newList;
).Если n
само по себе является простым, цикл for
вообще не будет выполнен, потому что if (PRIME(n))
вернет true.
Для каких входных аргументов будет FACTORISATION(int n)
вызываться (рекурсивно)?Обратите внимание, это будет называться для n, а затем для
н / п 1 ,
н / п 1 2,
..
н / п 1 a 1 ,
n/ p 1 a 1 p 2 ,
n / p 1 a 1 p 2 2 ,
..
n / p 1 a 1 p 2 a 2 ,
..
н / п 1 a 1 p 2 a 2 p 3 a 3 ... p k ,
..
н / п 1 a 1 p 2 a 2 p 3 a 3 ... p k a k -1 .
Тобыла самая сложная часть - если вы поняли это, все готово :) Теперь просто подытожьте время выполнения теста PRIME(n)
и время выполненияот выполнения for
цикла.Последний вносит общий вклад с (p 1 - 1) a 1 + (p 2 - 1) a 2 + ..+ (p k - 1) a k , в то время как первая часть добавляет n + n / p 1 + n / p 1 2 + ... + н / п 1 a 1 p 2 a 2 p 3 a 3 ... p k a k -1 .Невозможно оценить асимптотическую сложность этой суммы, не углубляясь в теорию чисел, но она намного лучше, чем O(n!)
(для верхней оценки суммы делителей см., Например, здесь ).