Ten minutes to understand: US data structures and algorithms - The time and space complexity

The complexity of the analysis is the essence of the entire algorithm to learn, once you have it, the contents of data structures and algorithms basically mastered the half.

1. What is the complexity of the analysis?

  1. Data structures and algorithms to solve is "how to make your computer faster time, space-saving and more to solve the problem."

  2. Thus for an execution time and space from two dimensions to evaluate the performance of the data structures and algorithms.

  3. Respectively time complexity and space complexity of the performance issues described two concepts, both collectively referred to as complexity.

  4. The complexity of the algorithm describes the growth of the relationship between the execution time (or space) and the data size.

2. Why was the complexity of the analysis?

  1. And performance tests compared to the complexity of the analysis is not dependent on the execution environment, low cost, high efficiency, easy operation, guidance and strong features.

  2. Grasp the complexity of the analysis, we will be able to write better code performance, help reduce system development and maintenance costs.

3. How to perform complex analysis?

3.1 Big O notation

And the number of execution time of the algorithm is proportional to each line of code, with T (n) = O (f (n)), where T (n) represents the total execution time of the algorithm, f (n) represents a total for each line of code number, and n is often expressed scale data. This is the big O time complexity notation.

3.2 Time Complexity

1) the definition of

Time complexity of the algorithm, which is a measure of time of the algorithm.

Big O time complexity notation does not actually perform the specific code indicating real time, but rather code execution time with the scale of growth trends in data , it is also called progressive time complexity , short time complexity (asymptotic time complexity) .

Example 1:

function aFun() {
    console.log("Hello, World!");      //  需要执行 1 次
    return 0;       // 需要执行 1 次
}

Then this method of operation needs to be performed twice.

Example 2:

function bFun(n) {
    for(let i = 0; i < n; i++) {         // 需要执行 (n + 1) 次
        console.log("Hello, World!");      // 需要执行 n 次
    }
    return 0;       // 需要执行 1 次
}

Then this approach requires (n + 1 + n + 1) = 2n +2 ​​computation times.

Example 3:

 function cal(n) {
   let sum = 0; // 1 次
   let i = 1; // 1 次
   let j = 1; // 1 次
   for (; i <= n; ++i) {  // n 次
     j = 1;  // n 次
     for (; j <= n; ++j) {  // n * n ,也即是  n平方次
       sum = sum +  i * j;  // n * n ,也即是  n平方次
     }
   }
 }

Note that this is a two-for-loop, the second layer is performed n-* = n-n- 2 times, and the cycle is here ++ i, 2 and examples are i ++, is different, and the first increase after adding difference.

Then this approach requires (n- 2 + n- 2 + n-n-+ + + 1'd. 1. 1 +) = 2N 2 + 2N +. 3.

2) Features

To the complexity of the time, for example, because the time complexity describes the algorithm execution time and data size growth trends , so constant, low-level, the coefficient does not actually have a decisive impact on this growth trend, so do the time complexity when analyzing ignore these entries.

Therefore, the above example of a time a complexity of T (n) = O (1), the time of Example 2 complexity of T (n) = O (n ), an example of the time 3 complexity of T (n) = O (n- 2 ).

3.3 Time Complexity Analysis

    1. Only concerned with the number of cycles to execute up to a piece of code

Single frequency of the code to see: such as loops.

function cal(n) { 
   let sum = 0;
   let i = 1;
   for (; i <= n; ++i) {
     sum = sum + i;
   }
   return sum;
 }

Is most often performed for the code inside the loop and is performed n times, the time complexity is O (n).

    1. Addition rule: the complexity of the overall complexity equal to the magnitude of the largest part of the code of

Taking the maximum multi-segment codes: a code such as a single cycle and multiple cycle there, then the complexity of taking multiple cycles.

function cal(n) {
   let sum_1 = 0;
   let p = 1;
   for (; p < 100; ++p) {
     sum_1 = sum_1 + p;
   }

   let sum_2 = 0;
   let q = 1;
   for (; q < n; ++q) {
     sum_2 = sum_2 + q;
   }
 
   let sum_3 = 0;
   let i = 1;
   let j = 1;
   for (; i <= n; ++i) {
     j = 1; 
     for (; j <= n; ++j) {
       sum_3 = sum_3 +  i * j;
     }
   }
 
   return sum_1 + sum_2 + sum_3;
 }

The above code is divided into three parts, seeking sum_1, sum_2, sum_3, see the main part of the cycle.

The first part, seeking sum_1, know exactly performed 100 times, and regardless of the size of n, the execution time is a constant, and does not reflect the growth trend , so the time complexity is O (1).

Second and third portions, and seeking sum_2 sum_3, and time complexity is related to the size of n, is not to O (n) and O (n 2 ).

Therefore, taking the maximum magnitude of the three sections of the code, the final example above, the time complexity is O (n- 2 ).

Similarly analogy, if there are three layers for loop, the time complexity is O (n- 3 ),. 4 layer is O (n- . 4 ).

Therefore, the total time complexity is equivalent to the time complexity of the order of the largest part of the code .

    1. Multiplication Rule: complexity of nested tags is equal to the product of the nested inner and outer code complexity

Nested tags product requirements: such as recursive, multi-cycle and the like.

function cal(n) {
   let ret = 0; 
   let i = 1;
   for (; i < n; ++i) {
     ret = ret + f(i); // 重点为  f(i)
   } 
 } 
 
function f(n) {
  let sum = 0;
  let i = 1;
  for (; i < n; ++i) {
    sum = sum + i;
  } 
  return sum;
 }

F cal method calls inside the loop method, but there is also a method f cycle.

Therefore, the entire time CAL () is a function of the complexity, T (n-) = Tl (n-) T2 * (n-) = O (n-n-*) = O (n- 2 ).

    1. Scale for a plurality of adders: two parameters such as frequency control method has two cycles, then the time complexity of adding whichever
function cal(m, n) {
  let sum_1 = 0;
  let i = 1;
  for (; i < m; ++i) {
    sum_1 = sum_1 + i;
  }

  let sum_2 = 0;
  let j = 1;
  for (; j < n; ++j) {
    sum_2 = sum_2 + j;
  }

  return sum_1 + sum_2;
}

The above code is the sum, sum_1 data size is m, the data scale for sum_2 is n, so that the time complexity of O (m + n).

Equation: T1 (m) + T2 (n) = O (f (m) + g (n)).

    1. A plurality of scale for multiplication: such method has two parameters control the number of times of two cycles, then the time taken by multiplying the complexity of both
function cal(m, n) {
  let sum_3 = 0;
   let i = 1;
   let j = 1;
   for (; i <= m; ++i) {
     j = 1; 
     for (; j <= n; ++j) {
       sum_3 = sum_3 +  i * j;
     }
   }
}

The above code is summed for two cycles, the data size of the request sum_3 m and n, so the time complexity of O (m * n).

Equation: T1 (m) * T2 (n) = O (f (m) * g (n)).

3.4 common time complexity analysis

    1. Polynomial order: With the growth of data size, algorithm execution time and space occupancy, increase in proportion polynomial.

Include O (1) (a constant order), O (logn) (of the order), O (n) (linear order), O (nlogn) (linear logarithmic order), O (n- 2 ) (order of the square), O (n- . 3 ) (cubic order).

In addition to O (logn), O (nlogn), the other can be seen from the above examples.

Exemplified below O (logn) (of the order) :

let i=1;
while (i <= n)  {
   i = i * 2;
}

1 from the start code, each loop is multiplied by 2, when more than n, the loop ends.

In fact, high school had geometric series, i is the value of a geometric sequence. In mathematics there is like this:

20 21 22 ... 2k ... 2x = n

So long as we know how much is the value of x, we know that the number of lines of code executed, and by solving x 2x = n, was solving math = log x 2 the n-. Therefore, the time complexity of the above code is O (log 2 n-).

In fact, whether in the base 2 to 3 for the bottom, or base 10, we can put all the time complexity of the order are recorded as O (logn). why?

Because the number can be converted between each other, log3n = log . 3 2 * log 2 n-, so O (log . 3 n-) = O (C * log 2 n-), where = log C . 3 2 is a constant.

Since the time complexity describes the algorithm execution time and data size growth trends , so constant, low-level, the coefficient does not actually have a decisive impact on this growth trend, so the time complexity of doing analysis ignored these items.

Therefore, in representation of the complexity of the order of time, we ignore the logarithm of the "bottom", collectively as O (logN) .

Exemplified below O (nlogn) (of the order) :

function aFun(n){
  let i = 1;
  while (i <= n)  {
     i = i * 2;
  }
  return i
}

function cal(n) { 
   let sum = 0;
   for (let i = 1; i <= n; ++i) {
     sum = sum + aFun(n);
   }
   return sum;
 }

aFun time complexity is O (logn), and cal time complexity is O (n), so that the time code above the complexity of T (n) = T1 (logn) * T2 (n) = O (logn * n) = O (nlogn).

    1. Non-polynomial order: With the growth of data size, execution time and space occupancy jumped algorithm, such algorithms poor performance.

It includes O (2 n- ) (step index), O (n!) (Order factorial).

O (2 n- ) (step index) Examples:

aFunc( n ) {
    if (n <= 1) {
        return 1;
    } else {
        return aFunc(n - 1) + aFunc(n - 2);
    }
}

Answer:
Obviously running times, T (0) = T ( 1) = 1, while the T (n) = T (n - 1) + T (n - 2) + 1, where 1 is an addition counted once carried out.
Clearly T (n) = T (n - 1) + T (n - 2) is a Fibonacci number , can be shown by induction to prove, when n> = 1 T (n) <( 5/3) n- , while when n> 4 when T (n-)> = (] 3/2) n- .
Therefore, the time complexity of this method may be represented as O ((5/3,) n- ), later shortened to O (2 n- ).
Visible required for this method of running time is exponential rate of growth.
If you're interested, you can try running time of the algorithm are to test the next input size 1,10,100, I believe we will feel the endless charm of time complexity.

3.5 Time Complexity Category

Time complexity can be divided into:

  • Best-case time complexity (best case time complexity): In the best case execution time complexity of this code.
  • The worst case time complexity (worst case time complexity): In the worst case, the complexity of the execution time of this code.
  • Where the average time complexity (average case time complexity), expressed as a weighted average of the number of code execution in all cases. Also known as the weighted average time complexity or time complexity desired .
  • The complexity of shared equally time (amortized time complexity): a high level of complexity and timing relationships has occurred, can be individual high-level complexity of most of the complexity of the code execution in all cases is the low-level complexity of the individual case an equal share to the low level of complexity. Results substantially equal to the low-level shared equally complexity.

for example:

// n 表示数组 array 的长度
function find(array, n, x) {
  let i = 0;
  let pos = -1;
  for (; i < n; ++i) {
    if (array[i] == x) {
      pos = i; 
      break;
    }
  }
  return pos;
}

find function is the function found in an array of key value equal to x, and returns the index value, it returns -1 if not found.

Best-case time complexity, the worst case time complexity

If the first value in the array is equal to x, then the time complexity is O (1), if the variable is not present in the array x, then we all need to traverse the entire array again, it would be time complexity O (n) . Therefore, under different circumstances, the time complexity of this code is not the same.

Therefore, the above code 最好情况时间复杂度is O (1), 最坏情况时间复杂度to O (n).

The average case time complexity

How to analyze the average time complexity? Code complexity magnitude differences appear in different situations, then a weighted average of the number of executions under the code all possible cases.

Variable x to find a position in the array, there are n + 1 case: 0 ~ n-1 in the position of an array and not in the array. In each case we find the number of elements required to traverse the added up and then divided by n + 1, can be obtained the average number of elements need to be traversed, i.e.:

Omitted factor, low-order, constant, so that, after the simplified equation, obtained 平均时间复杂度is O (n).

We know that you are looking for the variable x, either in the array or not in the array. In both cases the corresponding probability and statistics lot of trouble, we assume that the probability is not in the array and the array are both 1/2. Further, the data to find the probability of occurrence of 0 ~ n-1 in which n positions is the same for 1 / n. Therefore, according to the laws of probability multiplication, the data to find the probability of occurrence of 0 ~ n-1 at an arbitrary position is 1 / (2n).

Therefore, the biggest problem the previous derivation is that there is no probability of the occurrence of a variety of circumstances into account. If we put the probability of occurrence of each case is also taken into account, the calculation that the average time complexity becomes this:

This value is the probability theory weighted average , also called the expected value , the average time complexity of the full name should be called the weighted average time complexity or time complexity expectations .

Therefore, the conclusion derived from the above, obtained 平均时间复杂度is still O (n).

Amortized time complexity

Amortized time complexity is the complexity of a special kind of mean time (scenario very special, very limited, do not say here).

3.6 Time Complexity summary

Common time complexity time taken from small to large are:

O(1) < O(logn) < (n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)

Common time complexity:

3.7 complexity of spatial analysis

Complexity time stands for progressive time complexity , represents a growth of the relationship between the execution time of the algorithm and the data size .

Analogy about the space complexity is the full name of the complexity of progressive space (asymptotic space complexity), it represents the growth of the relationship between algorithms and data storage space scale .

Definition: space complexity of the algorithm implemented by calculating the required storage space, the space complexity of the algorithm referred to as the formula: S (n-) = O (F (n-)) , where, n-scale of the problem is, f (n) as a function of n statement occupied storage space.

function print(n) {
 const newArr = []; // 第 2 行
 newArr.length = n; // 第 3 行
  for (let i = 0; i <n; ++i) {
    newArr[i] = i * i;
  }

  for (let j = n-1; j >= 0; --j) {
    console.log(newArr[i])
  }
}

Like the time complexity analysis, we can see that the second line of code, we applied for a space to store variable newArr, an empty array. Line 3 newArr length changes the length of the array is n, each of the value is undefined, in addition, the rest of the code does not take up more space, so that the whole space of code complexity is O ( n).

Our common space complexity is O (1), O (the n-), O (the n- 2 ), like O (logn), O (nlogn ) such order of complexity are usually less than.

4. How to master the complexity analysis?

The key is to analyze the complexity of the more training, the so-called Practice makes perfect.

Usually when we write code, is to use space for time or time for space, it can be measured based on the time complexity and space complexity degrees.

5. Finally

If you think of this article or item you have inspired to praise or Give me a star, right, thumbs up is a virtue, thank you.

I often more articles address: GitHub

Reference article:

The complexity of the analysis (on): how to analyze the efficiency of algorithms and resource consumption statistics?
(Data structure) ten minutes to get the time complexity of the algorithm

Guess you like

Origin www.cnblogs.com/biaochenxuying/p/11479168.html
Recommended