大 O 表示法(Big-O Notation)
大 O 表示法是一种用于描述算法复杂性的数学符号,主要用于衡量算法的效率,特别是随着输入规模增大时算法的运行时间或占用空间的增长趋势。
基本概念
-
时间复杂度
- 描述算法所需的运行时间如何随输入数据规模 n 增大而增长。
- 表示形式:如 , , , 。
-
空间复杂度
- 描述算法所需的内存空间如何随输入数据规模 n 增大而增长。
- 表示形式:与时间复杂度类似,常见为 , 等。
-
渐进性描述
- 大 O 表示法不关注常数因子,只关注随着输入规模无限增长时的增长趋势。例如,若运行时间为 ,其渐进复杂度为 。
常见的时间复杂度
以下列举了一些常见的时间复杂度,从快到慢排序:
-
常数时间
- 算法的运行时间与输入规模无关。
- 示例:数组索引访问、变量赋值。
def constant_example(arr):return arr[0] # 只访问一次,无论数组多大
-
对数时间
- 每次操作将问题规模缩小(如二分查找)。
- 示例:二分查找。
def binary_search(arr, target):low, high = 0, len(arr) - 1while low <= high:mid = (low + high) // 2if arr[mid] == target:return midelif arr[mid] < target:low = mid + 1else:high = mid - 1return -1
-
线性时间
- 算法需要逐个处理输入的每个元素。
- 示例:线性搜索。
def linear_search(arr, target):for i, val in enumerate(arr):if val == target:return ireturn -1
-
线性对数时间
- 通常出现在排序算法(如归并排序、快速排序)。
def merge_sort(arr):if len(arr) <= 1:return arrmid = len(arr) // 2left = merge_sort(arr[:mid])right = merge_sort(arr[mid:])return merge(left, right)def merge(left, right):result = []i = j = 0while i < len(left) and j < len(right):if left[i] < right[j]:result.append(left[i])i += 1else:result.append(right[j])j += 1result.extend(left[i:])result.extend(right[j:])return result
-
平方时间
- 通常出现在嵌套循环中(如冒泡排序)。
- 示例:冒泡排序。
def bubble_sort(arr):n = len(arr)for i in range(n):for j in range(0, n-i-1):if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr[j]
-
指数时间
- 通常出现在递归问题中(如穷举所有子集)。
- 示例:斐波那契数列递归计算。
def fibonacci_recursive(n):if n <= 1:return nreturn fibonacci_recursive(n-1) + fibonacci_recursive(n-2)
-
阶乘时间
- 通常出现在全排列问题中,增长极快。
- 示例:旅行商问题暴力求解。
大 O 表示法的特性
-
忽略低阶项
- 复杂度表示只关注增长最快的项。例如,若 ,则复杂度为 。
-
忽略常数因子
- 只关注输入规模的增长趋势。例如,若 ,则复杂度为 ,忽略常数 5。
-
渐进上界
- 大 O 表示的是最坏情况下的增长速度,是算法复杂度的上界。
常见的空间复杂度
-
:常数空间
- 算法只使用固定数量的额外空间(如简单变量)。
-
:线性空间
- 算法需要额外的内存来存储与输入规模相等的数据量(如递归调用栈或结果数组)。
-
:平方空间
- 通常在动态规划表中出现,例如计算最长公共子序列。
优化算法复杂度的思路
-
降低循环嵌套层数
- 优化嵌套循环,减少重复计算。
-
利用分治法
- 将问题分解为更小的子问题,例如归并排序。
-
使用高效数据结构
- 选择合适的数据结构(如哈希表替代数组查找)。
-
动态规划
- 通过记录中间结果避免重复计算。
-
启发式算法
- 在复杂问题中,使用启发式方法找到近似解而不是穷举。
总结
大 O 表示法是描述算法性能的重要工具,帮助开发者选择和优化算法。理解常见的时间和空间复杂度,并结合问题特性选择适当的算法和数据结构,是提升算法效率的关键。