简体   繁体   English

时间复杂度是 O(n) 还是 O(n^2)?

[英]Is Time complexity O(n) or O(n^2)?

I feel that the time complexity of this js function I wrote is O(n) but at the same time it feels like its O(n^2).我感觉我写的这个js function的时间复杂度是O(n),但同时感觉它的时间复杂度是O(n^2)。 What's the correct time complexity?正确的时间复杂度是多少? The function is supposed to find the last index of the first duplicate item found. function 应该找到找到的第一个重复项的最后一个索引。 For example in the first example, 1 was found at index 0 and 1 was also found at index 6. So the result would be 6 because thats the last index of the first duplicate values in that array.例如,在第一个示例中,在索引 0 处找到 1,在索引 6 处也找到 1。因此结果将是 6,因为那是该数组中第一个重复值的最后一个索引。 If no duplicates found then we return -1.如果没有找到重复项,则返回 -1。

// [1, 2, 4, 5, 2, 3, 1] --> output: 6
// [1, 1, 3, 2, 4] --> output: 1
// [1, 2, 3, 4, 5, 6] --> output: -1(not found)
// It can be in any order, just need to find the last index of the first duplicate value thats there

const findFirstDuplicateIndex = (arr) => {
    let ptr1 = 0
    let ptr2 = 1   
    while (ptr1 < arr.length - 1) { // O(n)
        if(arr[ptr1] === arr[ptr2]) {
            return ptr2 + 1
        } else {
            ptr2++ 
        }
        if (ptr2 === arr.length - 1) {ptr1++; ptr2 = ptr1 + 1}
    }
   return -1
}

The time complexity of your code is O(n^2) .您的代码的时间复杂度为O(n^2)

Your code is another version of two nested loops.您的代码是两个嵌套循环的另一个版本。

if (ptr2 === arr.length - 1) {ptr1++; ptr2 = ptr1 + 1}

This code is equal to adding a nesting loop ie这段代码等于添加了一个嵌套循环,即

for(ptr2 = ptr1+1; ptr2 < arr.length; ; ++ptr2)

If we rewrite your code with two nested for loops, we have如果我们用两个嵌套的 for 循环重写你的代码,我们有

const findFirstDuplicateIndex = (arr) => {
    for(let ptr1=0; ptr1 < arr.length - 1; ++ptr1) {
      for(let ptr2=ptr1+1; ptr2 < arr.length; ++ptr2){
        if(arr[ptr1] === arr[ptr2]) {
            return ptr2
        }
      }
    }
    return -1;
}

Now,现在,

For the 1st iteration: the inner loop will cost N-1.
For the 2nd iteration: the inner loop will cost N-2.
For the 3rd iteration: the inner loop will cost N-3.
........................
........................
For the (N-1)th iteration: the inner loop will cost 1.

So, the total time complexity is the sum of the cost which is因此,总时间复杂度是成本的总和,即

(N-1) + (N-2) + (N-3) + . . . . + 1

which is an arithmetic series and by using the arithmetic sum formula we have这是一个算术级数,通过使用算术和公式,我们有

(N-1) + (N-2) + (N-3) + . . . . + 1 = (N-1)*(N-2)/2 = O(N^2)

Hence, the time complexity of your code is O(n^2) .因此,您的代码的时间复杂度为O(n^2)

In time complexity concept we have to asign a 1 value for declaring in loops we have to check the condition and after that we have to check how many times it will run and for return any value we have to add 1 and after completing we have to add alll.在时间复杂度概念中,我们必须分配一个 1 值来声明循环,我们必须检查条件,然后我们必须检查它将运行多少次,并返回任何值,我们必须加 1,完成后我们必须添加所有。

No matter, how you write it down, eventually.不管你怎么写,最终。 Your code runs the variable arr1 from 0..n-2 and your variable arr2 for each arr1 from arr1+1..n-1 .您的代码运行来自0..n-2的变量arr1和来自arr1+1..n-1的每个arr1的变量arr2 Which yields the O(N^2) (worst case) time complexity.这会产生O(N^2) (最坏情况)时间复杂度。

But since it is not as easy to spot for more complicated algorithms, one good way to assess the complexity is to have an instrumented version of the algorithm, where you simply count the number of steps.但由于更复杂的算法不容易发现,评估复杂性的一种好方法是拥有算法的检测版本,您只需计算步数即可。 And use pathologically worst case data as input.并使用病态最坏情况数据作为输入。

In your case, the worst case is, when the duplicate is positioned as the last 2 values in the array (eg [5 4 3 2 1 1] ).在您的情况下,最坏的情况是,当重复项定位为数组中的最后 2 个值时(例如[5 4 3 2 1 1] )。

So, in step 1, write yourself some test data generator:因此,在步骤 1 中,为自己编写一些测试数据生成器:

(defun gen-test-data (n)
  (make-array (+ n 1)
          :initial-contents
          (append
           (loop for x from n downto 1
             collecting x)
           '(1))))

It produces the pathological pattern in an array of length (n+1).它以长度为 (n+1) 的数组生成病理模式。

(gen-test-data 20) (生成测试数据 20)
#(20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 1) #(20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 1)

Next, write your instrumented algorithm, which returns a little extra information:接下来,编写您的检测算法,它会返回一些额外的信息:

(defun first-duplicate (data)
  (let* ((arr (etypecase data
                 ((simple-vector *) data)
                 (cons (make-array (length data)
                                   :initial-contents data))))
         (n (array-dimension arr 0)))
    (loop
      with counter = 0
      for i0 below (- n 1)
      do (loop
       for i1 from (+ i0 1) below n
       do (when (= (aref arr i0) (aref arr i1))
        (return-from first-duplicate
          (list :value (aref arr i0)
            :i0 i0
            :i1 i1
            :counter counter
            :n n)))
       do (incf counter)))))

I picked the nested loop notation here, because that is what you do anyway.我在这里选择了嵌套循环表示法,因为无论如何这就是你要做的。

The last step now is to run the function for various n, so you can see, how n relates to counter :现在的最后一步是为各种 n 运行 function,因此您可以看到 n 与counter的关系:

(loop for n from 2 to 100 by 10 collecting (first-duplicate (gen-test-data n))) (循环 n 从 2 到 100 由 10 收集(第一次重复(gen-test-data n)))
((:VALUE 1:I0 1:I1 2:COUNTER 2:N 3) ((:值 1:I0 1:I1 2:计数器 2:N 3)
(:VALUE 1:I0 11:I1 12:COUNTER 77:N 13) (:值 1:I0 11:I1 12:计数器 77:N 13)
(:VALUE 1:I0 21:I1 22:COUNTER 252:N 23) (:值 1:I0 21:I1 22:计数器 252:N 23)
(:VALUE 1:I0 31:I1 32:COUNTER 527:N 33) (:值 1:I0 31:I1 32:计数器 527:N 33)
(:VALUE 1:I0 41:I1 42:COUNTER 902:N 43) (:值 1:I0 41:I1 42:计数器 902:N 43)
(:VALUE 1:I0 51:I1 52:COUNTER 1377:N 53) (:值 1:I0 51:I1 52:计数器 1377:N 53)
(:VALUE 1:I0 61:I1 62:COUNTER 1952:N 63) (:值 1:I0 61:I1 62:计数器 1952:N 63)
(:VALUE 1:I0 71:I1 72:COUNTER 2627:N 73) (:值 1:I0 71:I1 72:计数器 2627:N 73)
(:VALUE 1:I0 81:I1 82:COUNTER 3402:N 83) (:值 1:I0 81:I1 82:计数器 3402:N 83)
(:VALUE 1:I0 91:I1 92:COUNTER 4277:N 93)) (:值 1:I0 91:I1 92:计数器 4277:N 93))

The output now clearly shows, that it cannot be O(N) and is rather O(N^2) . output 现在清楚地表明,它不可能是O(N)而是O(N^2)

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

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