for循环内递归分解函数的时间复杂度

时间:2019-07-03 02:24:14

标签: time-complexity big-o

这是我用伪代码编写的算法:它的作用是返回一个质数列表,该质数给出了n的因式分解。例如75 = 3 * 5 * 5

public static ArrayList<Integer> FACTORISATION(int n) {
    if (PRIME(n)) {
        // return a one-element array
        return new ArrayList<Integer>(Arrays.asList(n));
    } else {
        // find a prime divisor, p
        for (int i = 2; i < Math.sqrt(n); i++) {
            if (n % i == 0) {
                ArrayList<Integer> newList = new ArrayList<>();
                newList.add(i);
                newList.addAll(FACTORISATION(n/i));
                return newList;
            }
        }
    }
    return new ArrayList<>();
}

根据我的说法,时间复杂度可以计算为:-

T(n) = 2 + T(n-1/p) + T(n-2/p) +...
T(n) = nT(n-1/p)
T(n) = O(n!)

PRIME(n)方法的复杂度为O(n)

这正确吗?

1 个答案:

答案 0 :(得分:0)

有点复杂。首先,请更正代码中的错误,该错误应为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次,其中in的最小素数。这是因为,当首先找到这样的i时,循环终止(return newList;语句)。如果n本身是素数,则根本不会执行for循环,因为if (PRIME(n))将返回true。

将{递归)调用FACTORISATION(int n)的输入参数?请注意,它将先调用n,然后再调用

n / p 1

n / p 1 2

..

n / p 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

..

n / p 1 a 1 p 2 a 2 p 3 a 3 ... p k

..

n / p 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 + ... + n / p 1 a 1 p < sub> 2 a 2 p 3 a 3 。 .p k a k -1 。在没有认真研究数论的情况下,不可能评估该和的渐近复杂性,但是它比O(n!)好得多(关于除数之和的上限,请参见here)。