我如何找到这段代码的空间和时间复杂度

问题描述

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))!)