问题描述
fun root(n) =
if n>0 then
let
val x = root(n div 4);
in
if (2*x+1)*(2*x+1) > n then 2*x
else 2*x+1
end
else 0;
fun isPrime(n,c) =
if c<=root(n) then
if n mod c = 0 then false
else isPrime(n,c+1)
else true;
此处 root(n) 函数的时间复杂度为 O(log(n)):数字在每一步都除以 4,函数本身的代码为 O(1)。 isPrime 函数的时间复杂度是 o(sqrt(n)),因为它从 1 到 sqrt(n) 迭代运行。我现在面临的问题是这两个函数的顺序是什么?它只是 O(sqrt(n)) 还是 O(sqrt(n)*log(n)) 或其他的东西?
总的来说,我是大 O 符号的新手,我浏览了多个网站和 YouTube 视频,试图理解这个概念,但我似乎无法自信地计算它......如果你们能指点我的话一些帮助我练习计算的资源,这将是一个很大的帮助。
解决方法
root(n)
是 O(log₄(n)),是的。
isPrime(n,c)
是 O((√n - c) · log₄(n)):
- 您在每一步都重新计算
root(n)
,即使它从未改变,导致“...·log₄(n)”。 - 您将
c
从某个值迭代到root(n)
;虽然它由root(n)
向上有界,但它不是向下有界:c
可以从 0 开始,或从任意大的负数开始,或从小于或等于 √ 的正数开始n,或大于 √n 的数字。如果您假设c
从 0 开始,那么isPrime(n,c)
是 O(√n · log₄(n))。
您可能想使用归纳法或参考主定理来证明这一点。您可能希望简化 isPrime
,使其不会将 c
作为其外部签名中的参数,并且不会在每次迭代时不必要地重新计算 root(n)
。
例如:
fun isPrime n =
let
val sq = root n
fun check c = c > sq orelse (n mod c <> 0 andalso check (c + 1))
in
check 2
end
这个 isPrime(n)
是 O(√n + log₄(n)),或者如果我们省略低阶项,则只是 O(√n)。
首先它在 O(log₄(n)) 处计算 root n
一次。
然后它在 O(√n) 处从 0 循环到 root n
一次。
请注意,此时我们都没有正式证明任何事情。
(编辑:已将 check (n,0)
更改为 check (n,2)
,因为废话。)
(编辑:从n
中删除了作为参数的check
,因为它永远不会改变。)
(编辑:正如你所指出的,Aryan,从 2 到 root n
循环确实是 O(√n),即使计算 { {1}} 只需要 O(log₄(n))!)