假设我有getNumber()返回一个整数,该整数存储在我在main中实例化的类中。
public int getNumber()
{
return number;
}
上面的代码取O(1),下面的代码取O(2)吗?还是我误解了O表示法在完成操作的CPU周期方面的作用?
public int getNumber()
{
int myNumber = number;
return myNumber;
}
因此改述我的问题,在一行上返回一个对象的变量是否与在声明另一个变量来保存该对象的变量然后在另一行中返回它的性能相同?
答案 0 :(得分:1)
Big-O标记不是要计算确切的CPU周期数,而是要计算相对于一些变化的大小(例如,输入的长度)的数量级。在此,两个函数均具有恒定的运行时间,该运行时间不依赖于任何其他大小,因此均为O(1)。
(顺便说一下,在任何实际情况下,我都希望有一个不错的编译器内联int myNumber = number
行,并使两个函数声明基本相同)
答案 1 :(得分:1)
第一件事:大的O表示法是功能的分类,符号O(n)
代表从ℝ到ℝ的所有函数的 set 增长最快/快于函数 f(n)= n 的任何正数倍。
此技术介绍(在此范围内进行了缩小)是必要的,以明确使用大的O表示法来表示函数的增长速度/程度。
因此,我们不会考虑确切的倍数: 10n , 5n 和 20n 都是O(n)
,因为它们是函数n
的倍数。
尽管类似O(5n)
之类的符号有点滥用(我们有多个符号表示与O(n)
相同的集合),但它们还是经常使用。
大O表示法需要一个函数来度量,在计算复杂度理论中,两个主要函数度量是时间复杂度和空间复杂度。
时间复杂度是一种函数,用于测量算法根据生成的 length 的 length 函数所采用的步骤的数量 em>(例如,输入10
为长度2,两位数)。
这里有一个隐藏的陷阱,什么是 step ?
仅当给定了计算模型时,该步骤才是步骤,换句话说,首先需要确定如何进行计算,可以执行哪些步骤。
在文献中很少对此进行明确或明确的说明,我不知道为什么。
例如,指令a = b + c
通常被视为单个步骤,这是因为所使用的计算模型是编写程序所用的高级语言。
但是,在某些情况下,a = b + c
不被视为单个步骤,而这样的上下文就是 bit-complexity ,该模型将每个位的每个操作都视为单个步骤(因此该指令将为O(m)
,其中m
是数字的长度(以位为单位)。
在您的示例中,第一个实现的复杂度为O(1)
,因为函数体内只有一条语句。
第二个有两个语句,其中之一是变量初始化。由计算模型决定是否要根据常量表达式初始化的变量(请注意它们是否从必须在运行时计算的值中获取值)是否计为一个步骤。
您可以放心地假设它们总是这样做,因为它们最多会使总成本增加O(1)
,而总成本将由函数主体中的任何代码控制(除非函数主体仅具有可变的初始化)。
因此,第二个功能的成本为O(2)
(滥用符号),但根据定义为O(2) = O(1)
。
这应该澄清对CPU周期的误解。当使用高级语言来描述我们不关心CPU周期的算法时,我们的计算模型就是一台可以直接理解该高级语言的机器!之所以如此,是因为我们不知道如何将其转换为汇编指令,因此无法计算CPU周期。
请记住,时间复杂度与时间无关,它与时间无关,它与许多步骤有关,而不与经过的滴答声有关。
当使用高级语言时,所隐含的计算模型就是该语言的每个陈述都是一个步骤。
另外要注意的一点是:时间复杂度与大O表示法不能用来过于紧密地衡量性能。常数小的O(n^2)
比常数大的O(n)
更好,对于问题的任何实际实例化,常数总是大于n
的任何可能值。
但这很麻烦(通常可以在数值方法上找到),因为一般的概述常数可以删除。确实,这是一个很好的工具,因为否则分析将过于复杂。