简体   繁体   English

如果我调用一个 function,它在一个 for 循环中包含一个 for 循环,那是 O(n^2) 时间还是 O(n)?

[英]If I call a function that contains a for loop inside a for loop, is that considered O(n^2) time or O(n)?

for loop inside subArraySum calls sumArray which also contains a for loop. subArraySum 内的 for 循环调用 sumArray,它也包含一个 for 循环。 Would this be considered O(n^2) time?这会被认为是 O(n^2) 时间吗? Go easy on me as this is my first ever question and as you can see from my code, I'm a beginner. Go 对我来说很简单,因为这是我的第一个问题,正如您从我的代码中看到的那样,我是初学者。 This is my code:这是我的代码:

const subArraySum = (arr,n) => {
    let i = 0;
    let result = [];
    for (let j = n-1;j<arr.length;j++) {
        let li = arr.slice(i,j+1);
        result.push(sumArray(li));
        i++;
    }
    return maxResult(result);
}

function sumArray(li) {
    counter = 0;
    for (let k of li) {
        counter+=k;
    }
    return counter;
}

function maxResult(result) {
    let highest = 0;
    for (let k of result) {
        if (k>highest) {
            highest = k;
        }
    }
    return highest;
}

Yes, this makes it O(n^2), since complexity applies to the entire algorithm, not matter how it's split up into functions.是的,这使它成为 O(n^2),因为复杂性适用于整个算法,无论它如何拆分为函数。 Moving some code out to a named function doesn't change the overall running time or how it depends on the input.将一些代码移出命名函数不会改变整体运行时间或它如何依赖于输入。

Sometimes when we're calling built-in functions of the language or OS we may treat them as black boxes whose complexity is unknown, so we may ignore them for the purpose of calculating the complexity of our own algorithm.有时,当我们调用语言或操作系统的内置函数时,我们可能会将它们视为复杂度未知的黑盒子,因此我们可能会为了计算我们自己算法的复杂度而忽略它们。 But you can't usually ignore the complexity of your own functions that form part of your algorithm, since you have the option of redesigning them if there's a more efficient way.但是您通常不能忽略构成算法一部分的您自己的函数的复杂性,因为如果有更有效的方法,您可以选择重新设计它们。

While for and other looping constructs may provide some basic guides on complexity, the analysis must always consider the number of iterations and not rely on counting the number of nested loops.虽然for和其他循环结构可能会提供一些关于复杂性的基本指南,但分析必须始终考虑迭代次数,而不是依赖于计算嵌套循环的数量。 It can be easily shown that any number of nested loops can still result in linear or constant time complexity (ie while (true) { break; } ).可以很容易地证明,任意数量的嵌套循环仍然可以导致线性或恒定的时间复杂度(即while (true) { break; } )。

For the functions you mentioned, both sumArray and maxResult run n iterations, where n matches the count of input array elements.对于您提到的函数, sumArraymaxResult运行n次迭代,其中n与输入数组元素的计数相匹配。

For subArraySum , however, the complexity is not as trivial.然而,对于subArraySum ,复杂性并不那么简单。 We can easily see, that the function calls both sumArray and maxResult , however, it is not exactly clear how these invocations relate to the function inputs.我们可以很容易地看到,该函数同时调用sumArraymaxResult ,但是,尚不清楚这些调用与函数输入之间的关系。

To invoke subArraySum for some array arr of length m and an argument of n , we can see that the for loop runs from n - 1 to m , that is m - n + 1 times, or in complexity terms, the loop run count is a function of O(m - n + 1) = O(m - n) .要为某个长度为m数组arr和参数n调用subArraySum ,我们可以看到for循环从n - 1运行到m ,即m - n + 1次,或者在复杂性方面,循环运行次数为O(m - n + 1) = O(m - n) The constant 1 is considered insignificant for the purpose of asymptotic analysis (imagine the difference between 10 9 and 10 9 + 1 operations - probably not that much).对于渐近分析的目的,常数 1 被认为是微不足道的(想象一下 10 9和 10 9 + 1 操作之间的差异 - 可能没有那么多)。

Each loop then makes a sub-array of length n - 1 .每个循环然后制作一个长度为n - 1的子数组。 This is based on the i and j iteration variables - I may be wrong here but I suspect the implementation is.这是基于ij迭代变量 - 我在这里可能错了,但我怀疑实现是错误的。 Regardless, that makes an O(n) operation.无论如何,这都是一个O(n)操作。

The slice is then summed via sumArray (complexity of O(n) as described previously) and inserted to the back of another array (amortized O(1) ).然后通过sumArray (如前所述的O(n)复杂度)对切片进行求和,并插入到另一个数组的后面(摊销的O(1) )。

Therefore, each run of the loop has complexity of O(n) .因此,循环的每次运行都具有O(n)复杂度。

As the loop runs O(m - n) times and has a complexity of O(n) , yielding a total complexity of O(n * (m - n)) = O(m * n - n^2) .由于循环运行O(m - n)次并且具有O(n)复杂度,因此总复杂度为O(n * (m - n)) = O(m * n - n^2)

Let's now consider this term, m * n - n 2 .现在让我们考虑这个术语m * n - n 2 From the semantics of the function, we can assume, that it must always hold that n < m (the complexity is constant for n = m : m * n - n 2 = n 2 - n 2 = 0 - you can confirm this by mentally going through the algorithm, it would just return 0 without any looping).从函数的语义,我们可以假设,它必须始终保持n < m (对于n = m ,复杂性是常数: m * n - n 2 = n 2 - n 2 = 0 - 您可以通过以下方式确认这一点在精神上通过算法,它只会返回 0 而没有任何循环)。 If n is always smaller than m , then n 2 will always be smaller than m * n and therefore can be ignored.如果n始终小于m ,则n 2将始终小于m * n ,因此可以忽略。

We arrive at O(mn) for the loop.我们到达循环的O(mn)

At the end, maxResult is invoked for the array of sums which is O(m - n) long (remember that we created the array by running O(m - n) iterations, each adding a single number to the array).最后, maxResult长为O(m - n)的和数组调用maxResult (请记住,我们通过运行O(m - n)次迭代来创建数组,每次向数组添加一个数字)。 This gives us O(m - n) complexity for the maxResult call.这为maxResult调用提供了O(m - n)复杂度。

With complexity O(mn) + O(m - n) , we can, again apply the n < m and see that the second term always yields smaller value than the first one and therefore can be considered insignificant for the analysis.对于复杂度O(mn) + O(m - n) ,我们可以再次应用n < m并看到第二项总是产生比第一项小的值,因此可以认为对分析来说无关紧要。

So we arrive at the result, the algorithm has a time complexity of O(mn) where m is the length of the input array and n is the length of the sub-arrays.所以我们得出了结果,算法的时间复杂度为O(mn) ,其中m是输入数组的长度, n是子数组的长度。

It totally Depends on what kind of approach you're using inside of each for loop.这完全取决于您在每个 for 循环中使用哪种方法。

let us take simple example:-让我们举个简单的例子:-

if you're taking an a for loop which increments linearly (increments constantly till condition works) and inside it (in body) has a calling function which also has another linear for loop in it's body.如果你正在使用一个线性递增的 for 循环(不断递增直到条件起作用)并且在它内部(在主体中)有一个调用 function,它的主体中还有另一个线性 for 循环。

so, the time complexity will be O(n^2).因此,时间复杂度为 O(n^2)。 The second for loop will iterate through n for each call of the function by each iteration of the first for loop.第二个 for 循环将通过第一个 for 循环的每次迭代对 function 的每次调用迭代 n。 But it totally depends on what kind of incremental approach and conditions (any) you have for both for loop.但这完全取决于您对这两个 for 循环采用哪种增量方法和条件(任何)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM