我正在解决一些练习问题,我给出了目标时间复杂度和空间复杂度。其中一个给出目标时间复杂度为O(N + M)。我对O(N + M)算法看起来像什么的直觉有些麻烦。有没有人有像这样的算法的例子,或者可以清楚地解释它?我试图想到的每个例子对我来说都是O(N * M)。
答案 0 :(得分:19)
O(m+n)
算法的简单示例:
int sum(int[] nArr, int[] mArr) {
int sum = 0;
for(int i : nArr) {
sum += i;
}
for(int i : mArr) {
sum += i;
}
return sum;
}
要计算总和,您需要浏览nArr
(尺寸n
)中的所有元素和mArr
中的所有元素(尺寸m
),以便整体复杂度为O(m+n)
答案 1 :(得分:6)
O(n + m)算法的简单快速示例:
for (i = 0; i < n; i++)
{
// do something but don't loop or invoke recursive functions
// only constant O(c) complexity is allowed: a simple series of commands
}
for (i = 0; i < m; i++)
{
// idem
}
复杂度在添加时是可交换的(O(n + m)== O(m + n))这意味着您可以反转两个for()
而不影响复杂性。显然,在算法级别上,倒置的 MAY 不等同于直的。
作为额外的帮助,这里是O(n * m)算法的一个例子:
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
// do something but don't loop or invoke recursive functions
// only constant O(c) complexity is allowed: a simple series of commands
}
}
同样,您可以使用外部循环在内部进行反转,而不会影响复杂性(O(n * m)== O(m * n))。同样明显的考虑因素也适用。
你可以放入for()
主体的限制是因为big-o符号限制了上限。如果它是一个下限(小写符号)你可能会把更复杂的东西放进去,但它永远不会少于那个。
答案 2 :(得分:2)
以上所有答案均说明了O(n + m)的工作原理,但我想通过了解O(n m),O(n + m)有什么区别,从另一个角度看待它和O(n m)的主要区别是,将n乘以m表示n会发生m次或尝试m次,例如,下面的代码是O(n * m),因为n会在m次中发生n次
for(int i=0; i < n;i++){
for(int j=0; j < m;j++){
//some_code
}
}
答案 3 :(得分:1)
因此,为了扩展其他回复,我将尝试添加此类问题的示例以帮助您理解:
答案 4 :(得分:0)
一个非常重要的指导性示例是获取两个大小为M和N的排序数组,并输出一个包含所有这些元素的新排序数组。这是merge-sort的基础,将进行O(M + N)比较。
您可以在任何地方找到示例或自己动手。
答案 5 :(得分:-1)
这个问题的直觉是你有两个独特的变量n
和m
。现在想象这两个独特的变量独立增加,接近无穷大。
如果这是O(n)问题(即BIG-O),则该问题的复杂性的向上边界至少是线性的。你可以说O(n) = n^2
。但是O(n)问题永远不会接近n^2
限制,因为n
(输入)接近无限。
同样,m
的行为也是一样的。 O(m)
可以是m^2
。但是更准确地说O(m) = m
。这两个问题的复杂性是线性。
现在,如果您只是O(n+m)
,那真的是n^2
吗?它不应该。即使n=m
,总和也是2n
或2m
。此问题的复杂性仍然是线性,因为输出的大小仍然与输入n
和m
成比例。因此,此问题的最精确答案将是O(n+m) = n+m
。