这取决于你的意思。如果问题是关于普通数组的,这意味着一系列连续的内存位置,并且对于初始化,您的意思是在这个“矩阵”的每个内存位置放置一个值,那么答案是否定的,比 O(n*m) 更好是不可能的并且我们可以证明:
让我们假设算法fill(A[n][m], init_val)
是正确的(即填充 的所有内存位置)具有小于(意味着不是 的一部分)的A
复杂度,然后足够大,我们将拥有= 内存位置的数量。由于填充内存位置需要一个操作,因此算法可以填充大多数位置[实际上是一半,因为它还必须至少执行一个操作来“选择”不同的内存位置,除非硬件提供组合操作],这严格小于,这意味着算法不正确。g(n,m)
O(n*m)
g(n,m)
Ω(n*m)
n
m
g(n,m) < n*m
fill
g(n,m)
n*m
fill
如果填充内存位置需要恒定时间,这同样适用k
,您只需选择更大n
的m
值。
正如其他已经建议的那样,您可以使用其他数据结构来避免O(n^2)
初始化时间。amit 建议使用某种惰性求值,它允许您根本不初始化数组,而仅在访问元素时才这样做。
请注意,这Ω(n^2)
在开始时消除了成本,但需要更复杂的操作来访问数组的元素,并且还需要更多的内存。
目前尚不清楚面试官的意思:将数组转换为链表需要Ω(L)
时间(其中 L 是数组的长度),因此简单地将整个矩阵转换为链表需要Ω(n^2)
时间加上真正的初始化。使用递归根本没有帮助,您最终只会出现重复,例如T(n) = 2T(n/2) + O(1)
这将再次导致渐近复杂性没有任何好处。
作为一般规则,所有算法都必须至少扫描所有输入,除非它们事先具有某种形式的知识(例如,元素已排序)。在您的情况下,要扫描的空间是Θ(n^2)
,因此每个想要填充它的算法必须至少是Ω(n^2)
. 任何低于这个复杂度的东西要么做出一些假设(例如内存默认包含初始化值 -> O(1)
),要么解决不同的问题(例如使用惰性数组或其他数据结构)。