时间复杂度(Time Complexity)

0 阅读3分钟

时间复杂度(Time Complexity)

在上一节中我们介绍了 什么是算法

但有一个更重要的问题:

如果有多个算法可以解决同一个问题
哪一个更好?

例如:

算法A:计算 100 万次
算法B:计算 1

显然 算法B更快

但在程序中,我们不可能真的每次都去计算执行时间,所以计算机科学家提出了一种 评估算法效率的方法

时间复杂度

什么是时间复杂度

时间复杂度:描述算法运行时间随数据规模增长的变化趋势。

简单理解:

数据量变大时
算法会变慢多少

例如:

数据量 算法A 算法B


10 10次 1次 100 100次 1次 1000 1000次 1次

可以看到:

算法A的执行次数随着 n 增长
算法B几乎不变

所以:

算法B更优

大 O 表示法

时间复杂度通常用:

O(...)

表示。

读作:

Big O

例如:

O(1)
O(n)
O(n²)
O(log n)

它表示的是:

算法增长趋势

而不是 精确执行时间


常见时间复杂度

O(1) 常数时间

无论数据量多大,执行次数基本不变。

例如数组取值:

let arr = [10,20,30,40]
print(arr[2])

访问数组元素时:

只执行一次

所以:

时间复杂度 = O(1)

O(n) 线性时间

执行次数和数据量 成正比

例如遍历数组:

func printArray(_ arr: [Int]) {
    for num in arr {
        print(num)
    }
}

如果数组长度是:

n

循环就会执行:

n 次

所以:

时间复杂度 = O(n)

O(n²) 平方时间

常见于 嵌套循环

例如:

func printPairs(_ arr: [Int]) {
    for i in 0..<arr.count {
        for j in 0..<arr.count {
            print(arr[i], arr[j])
        }
    }
}

如果数组长度是:

n

执行次数是:

n × n

所以:

时间复杂度 = O(n²)

O(log n) 对数时间

这种复杂度通常出现在 每次减少一半数据 的算法中。

最经典例子:

二分查找

例如在一个有序数组中找数字:

1 3 5 7 9 11 13

查找:

7

步骤:

1 取中间值 7
2 找到

如果找不到:

每次排除一半数据

例如:

100万数据

查找次数大约:

20 次

所以:

时间复杂度 = O(log n)

常见复杂度排序

算法复杂度从 快到慢

O(1)
O(log n)
O(n)
O(n log n)
O(n²)
O(2^n)
O(n!)

实际开发中通常希望:

O(n log n) 以内

一个实际例子

问题:

判断数组中是否存在某个数字

方法1:遍历

func contains(_ arr: [Int], _ target: Int) -> Bool {
    for num in arr {
        if num == target {
            return true
        }
    }
    return false
}

时间复杂度:

O(n)

方法2:二分查找(数组有序)

func binarySearch(_ arr: [Int], _ target: Int) -> Bool {
    var left = 0
    var right = arr.count - 1
​
    while left <= right {
        let mid = (left + right) / 2
​
        if arr[mid] == target {
            return true
        } else if arr[mid] < target {
            left = mid + 1
        } else {
            right = mid - 1
        }
    }
​
    return false
}

时间复杂度:

O(log n)

如何快速判断时间复杂度

经验总结:

一个循环

O(n)

嵌套循环

O(n²)

每次减少一半

O(log n)

循环 + 二分

O(n log n)

为什么时间复杂度重要

假设:

n = 1,000,000

不同算法执行次数:

算法 执行次数


O(1) 1 O(log n) 20 O(n) 1,000,000 O(n²) 1,000,000,000,000

差距会非常巨大。


本节总结

时间复杂度用于:

衡量算法效率

常见复杂度:

O(1)
O(log n)
O(n)
O(n log n)
O(n²)

理解时间复杂度后,我们才能:

写出更高效的算法

下一课

下一节我们进入 第一个数据结构

数组(Array

你将学会:

  • 数组的底层原理
  • 为什么数组访问是 O(1)
  • 数组为什么插入很慢