time complexity时间复杂度

The time complexity of an algorithm is denoted O(…) where the three dots represent some function. Usually, the variable n denotes the input size.

  1. //O(n)
  2. for (int i = 1; i <= n; i++) {
  3. // code
  4. }
  1. //O(n^2)
  2. for (int i = 1; i <= n; i++) {
  3. for (int j = 1; j <= n; j++) {
  4. // code
  5. }
  6. }

A time complexity does not tell us the exact number of times the code inside a loop is executed, but it only shows the order of magnitude.

  1. //这些都是O(n)
  2. for (int i = 1; i <= 3*n; i++) {
  3. // code
  4. }
  5. for (int i = 1; i <= n+5; i++) {
  6. // code
  7. }
  8. for (int i = 1; i <= n; i += 2) {
  9. // code
  10. }
  1. //这就是O(n^2)的
  2. for (int i = 1; i <= n; i++) {
  3. for (int j = i+1; j <= n; j++) {
  4. // code
  5. }
  6. }

一段程序中,有多个程序段落,整个程序的时间复杂度跟 时间复杂度最大的段落走

  1. for (int i = 1; i <= n; i++) {
  2. // code
  3. }
  4. for (int i = 1; i <= n; i++) {
  5. for (int j = 1; j <= n; j++) {
  6. // code
  7. }
  8. }
  9. for (int i = 1; i <= n; i++) {
  10. // code
  11. }
  12. //这段代码,是O(n^2)的

还有O(nm)

  1. for (int i = 1; i <= n; i++) {
  2. for (int j = 1; j <= m; j++) {
  3. // code
  4. }
  5. }

recursion递归的时间复杂度

The time complexity of a recursive function depends on the number of times the function is called and the time complexity of a single call.

  1. void f(int n) {
  2. if (n == 1) return;
  3. f(n-1);
  4. }
  5. //The call f(n) causes n function calls,
  6. //and the time complexity of each call is O(1).
  7. //Thus, the total time complexity is O(n).

再看下面这一个

  1. void g(int n) {
  2. if (n == 1) return;
  3. g(n-1);
  4. g(n-1);
  5. }
  6. //g(n) 调用1次
  7. //g(n-1) 调用2次
  8. //g(n-2) 调用4次
  9. //1+2+4+ ... + 2^(n-1) = 2^n-1 = O(2^n)

在算法竞赛当中,会给出时间限制和空间限制,一般时间限制是1s,此时不能超过1e8
这个值是跑出来的经验值,取决于评测机环境,CCF官方评测机跑出来的,不能超过1e8,1e8也是危险的

例题,最大子段和

Given an array of n numbers, our task is to calculate the maximum subarray sum. from《编程珠玑》

  1. //举例
  2. -1 2 4 -3 5 2 -5 2
  3. //最大子段和是10
  4. 2 4 -3 5 2

算法1,O(n^3)

  1. int best = 0;
  2. for (int a = 0; a < n; a++) {
  3. for (int b = a; b < n; b++) {
  4. int sum = 0;
  5. for (int k = a; k <= b; k++) {
  6. sum += array[k];
  7. }
  8. best = max(best,sum);
  9. }
  10. }
  11. cout << best << "\n";

算法2,O(n^2)

  1. int best = 0;
  2. for (int a = 0; a < n; a++) {
  3. int sum = 0;
  4. for (int b = a; b < n; b++) {
  5. sum += array[b];
  6. best = max(best,sum);
  7. }
  8. }
  9. cout << best << "\n";

算法3,O(n)

Consider the subproblem of finding the maximum-sum subarray that ends at position k. There are two possibilities:

  1. 1. The subarray only contains the element at position k.
  2. 2. The subarray consists of a subarray that ends at position k 1,
  3. followed by the element at position k.

In the latter case, since we want to find a subarray with maximum sum, the subarray that ends at position k − 1 should also have the maximum sum. Thus, we can solve the problem efficiently by calculating the maximum subarray sum for each ending position from left to right.

  1. int best = 0, sum = 0;
  2. for (int k = 0; k < n; k++) {
  3. sum = max(array[k],sum+array[k]);
  4. best = max(best,sum);
  5. }
  6. cout << best << "\n";

aha,这是就是动态规划..

所以,你会了一个经典dp问题 当有人把动态规划认为是学习算法的里程碑,或者分水岭,此时,你已经悄然渡过


  1. // 另外一种,最大字段和的写法
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. int a[20], n;
  5. int main()
  6. {
  7. cin >> n;
  8. for (int i = 1; i <= n; i++) cin >> a[i];
  9. int maxn = -0x3f3f3f3f, area = 0;
  10. for (int i = 1; i <= n; i++){
  11. area += a[i];
  12. if (area > maxn) maxn = area;
  13. if (area < 0) area = 0; //另起炉灶
  14. }
  15. cout << maxn << '\n';
  16. return 0;
  17. }
  18. =================
  19. #include <bits/stdc++.h>
  20. using namespace std;
  21. int a[20], n;
  22. int dp[20];
  23. int maxn = -0x3f3f3f3f;
  24. int main()
  25. {
  26. cin >> n;
  27. for (int i = 1; i <= n; i++) cin >> a[i];
  28. for (int i = 1; i <= n; i++){
  29. dp[i] = max(dp[i - 1], 0) + a[i]; //另起炉灶
  30. maxn = max(maxn, dp[i]);
  31. }
  32. cout << maxn << '\n';
  33. return 0;
  34. }

大纲要求

•【1】算法概念

•【2】算法描述:自然语言描述、流程图描述、伪代码描述