Java 恒定时间/空间复杂性概念的混淆

Java 恒定时间/空间复杂性概念的混淆,java,algorithm,time-complexity,co,Java,Algorithm,Time Complexity,Co,我对恒定时间/空间复杂性的概念感到困惑 例如: public void recurse(int x) { if(x==0) return; else recurse(x/10); } 其中,1恒定时间或空间意味着算法使用的时间和空间不依赖于输入的大小 恒定时间(因此O(1))算法 public int square(int x){ return x * x; } 因为对于任何输入,它都进行相同的乘法运算,并且结束了 另一方面,对数组中的所有元素求和 public in

我对恒定时间/空间复杂性的概念感到困惑

例如:

public void recurse(int x) {
    if(x==0) return;
    else recurse(x/10);
}

其中,1恒定时间或空间意味着算法使用的时间和空间不依赖于输入的大小

恒定时间(因此O(1))算法

public int square(int x){
    return x * x;
}
因为对于任何输入,它都进行相同的乘法运算,并且结束了

另一方面,对数组中的所有元素求和

public int sum(int[] array){
    int sum = 0;
    for(int i : array) sum += i;
    return sum;
}
需要O(n)个时间,其中n是数组的大小。它直接取决于输入的大小

空间复杂性的表现是相同的


任何不依赖于任何输入大小的东西都被认为是常数。

当你的算法不依赖于输入大小时,它被认为具有恒定的时间复杂度。例如:

function print(int input) {
  // 10 lines of printing here

}
在这里,无论您作为“输入”传入什么,函数体语句都将始终运行10次。如果将“input”传递为10,则运行10条语句。如果将“input”传递为20,则仍将运行10条语句

现在,另一方面,考虑一下:

function print(int input) {

  // This loop will run 'input' times
  for(int i=0;i<input;i++){
      System.out.println(i);
   }

}
功能打印(int输入){
//此循环将运行“输入”次

对于(int i=0;i在分析算法的时间和空间复杂性时,我们必须忽略物理计算机的一些限制;复杂性是“输入大小”的函数n,在大O表示法中是一个渐近上界,因为n趋于无穷大,但物理计算机当然不能对任意大的n运行算法,因为它有有限的内存和其他存储

因此,为了以一种有意义的方式进行分析,我们在一种虚构的计算机上分析算法,在这种计算机上,数组的长度没有限制,整数可以“足够大”为了使算法工作,等等。您的Java代码是该算法的具体实现,但该算法作为一个抽象概念存在,超出了Java在真实计算机上可能实现的范围。因此,在没有此类限制的虚拟计算机上运行此抽象算法,空间复杂度为O(logn)

这种“虚拟计算机”可能听起来有点模糊,但它可以通过数学形式化,以便严格地进行分析;它被称为a。在实践中,除非你在做学术研究,否则你不需要严格地分析算法,因此更有用的是接受模糊的概念,即你应该忽略任何限制这将阻止算法在任意大的输入上运行。

这实际上取决于您为什么使用大O表示法

从技术上讲,如果任何算法只适用于有限数量的可能输入,那么它就是O(1)。例如,这将是一个O(1)排序算法:“读取输入的前10^6位。如果输入中还有更多位,则输出“错误”。否则,则为bubblesort。”

但这种表示法的好处在于,它通常很好地近似于程序的实际运行时间。虽然O(n)算法也可以执行10^100*n运算,但通常情况并非如此,这就是为什么我们使用大O表示法的原因。这种规则的例外情况称为,最著名的是

总而言之,如果你想成为一名技术人员并赢得与朋友的争论,你可以说你的算法是O(1)。如果你想实际使用界来近似它的速度,你应该做的是想象它适用于任意大的数字,并将其称为O(log(n))

旁注:将此算法称为O(log(n))有点不正式,因为从技术上讲,复杂性需要用输入的大小来表示,而不是用输入的大小来表示,因此它是O(n)。经验法则是:如果你处理的是小数字,请用大小来表示复杂性-每个人都会理解。如果你处理的是可能有数百万位数的数字,请用长度来表示复杂性。在这种情况下,乘法等“简单”运算的成本(对于较小的数字,通常被认为是O(1))也需要考虑在内。

正如您所发现的,将渐近复杂性应用于真实世界是一件棘手的事情

渐近复杂性处理输入大小N没有上限的抽象情况,您只关心任意大的输入大小会发生什么

在现实世界中,在您感兴趣的实际应用程序中,输入大小通常有一个上限。上限可能是因为您没有无限的资源(时间/金钱)来收集数据。也可能是技术限制造成的,例如Java中固定大小的
int
数据类型

由于渐近复杂性分析没有考虑现实世界的限制,
recurse(x)
的渐近复杂性是O(logx)。尽管我们知道x只能增长到2^31。

(1)和(2)是一样的。你可以除以10的次数是小数位数。你的函数是O(logn))。