文章
学习
从 Python 到 Data/AI 一年计划成果第 8 / 10 篇

Week 4 学习成果|Big-O 与四类基础算法

Week 4 的实际产出:掌握 O(1) < O(log n) < O(n) < O(n log n) < O(n²) 的增长阶梯,手写线性搜索、二分查找、插入排序、归并排序,并得出「常数决定起跑线,Big-O 决定天花板」的实验结论。

PythonWeek4算法Big-O复杂度二分查找排序学习成果

本篇与一年学习计划总纲 Phase I 的 Week 4 · 算法与复杂度 一致,按总纲「每周固定执行模板」编排。Week 4 暂无单独的计划篇,本篇先记录实际成果。

🎯 本周目标

L3

  • ✅ 能判断时间复杂度、空间复杂度与最坏情况

📚 Core Knowledge

  • Big-O 与复杂度增长阶梯,最坏 / 平均 / 最好情况的区别
  • 递归与分治的直觉
  • 线性搜索、二分查找
  • 插入排序、归并排序

✍️ Human Core

  • 手写线性搜索
  • 手写二分查找
  • 手写插入排序
  • 手写归并排序

🧪 Experiment

Hypothesis

  • 运行时间由「常数」和「增长阶」共同决定:小规模时常数可能反超,规模变大后 Big-O 主导。

Experiment

  • 比较 O(n) / O(n log n) / O(n²) 三类算法在不同数据规模下的运行表现。

Result

  • 小规模下常数小的实现更快;规模增大后,增长阶低的一方稳定胜出。

Conclusion

  • 常数决定起跑线,Big-O 决定天花板。

📝 数智工程师考试映射

  • 时间 / 空间复杂度分析与最坏情况
  • 基础排序与查找算法

✅ Acceptance

  • 能判断常见算法的时间、空间复杂度与最坏情况
  • 能说清二分查找为什么要求数据有序、复杂度为何是 O(log n)

🧠 本周最重要的问题

常数和 Big-O,各自在什么规模下决定胜负?

小数据量时循环常数和分支开销占主导,写法更朴素的 O(n²) 可能更快;一旦规模放大,增长阶更低的一方必然反超。所以选算法先看增长阶,再看常数。

❓ 尚未解决

  • 归并排序的递归栈空间分析、快排的最坏情况还没展开。
  • 复杂度只到「会判断」,没有系统推导过均摊分析。

📊 Final Level

L3

复杂度增长阶梯

阶典型场景
O(1)哈希表命中、数组按下标取
O(log n)二分查找、平衡树查找
O(n)一次遍历
O(n log n)归并 / 快排、基于比较的排序下界
O(n²)双层循环、朴素插入排序

默认用最坏情况分析:同一个算法,最好 / 平均 / 最坏常常不是同一阶。

四种算法

# 线性搜索 O(n)
def linear_search(a, target):
    for i, x in enumerate(a):
        if x == target:
            return i
    return -1

# 二分查找 O(log n),要求已排序
def binary_search(a, target):
    lo, hi = 0, len(a) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if a[mid] == target:
            return mid
        if a[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1

# 插入排序 O(n²),近乎有序时接近 O(n)
def insertion_sort(a):
    for i in range(1, len(a)):
        key, j = a[i], i - 1
        while j >= 0 and a[j] > key:
            a[j + 1] = a[j]
            j -= 1
        a[j + 1] = key
    return a

# 归并排序 O(n log n),稳定
def merge_sort(a):
    if len(a) <= 1:
        return a
    mid = len(a) // 2
    left, right = merge_sort(a[:mid]), merge_sort(a[mid:])
    out, i, j = [], 0, 0
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            out.append(left[i]); i += 1
        else:
            out.append(right[j]); j += 1
    return out + left[i:] + right[j:]

实验结论

小数据量时,常数小、循环更简单的插入排序可能反超归并排序;数据量一放大,O(n log n) 就稳定压过 O(n²)。常数决定起跑线,Big-O 决定天花板。

来源与延伸阅读

  1. 01Week 1 学习计划|Python 对象模型与数据结构week-1计划
  2. 02一年学习计划:从 Python 到 Data/AI 系统的 52 周计划
  3. 03Week 1 学习成果|复杂度实测、对象模型与数据结构实战week-1成果
  4. 04Week 2 学习计划|Python 函数、作用域、闭包与模块化week-2计划
  5. 05Week 2 学习成果|闭包、decorator 与工程化重构week-2成果
  6. 06Week 3 学习计划|异常、测试与 Debuggingweek-3计划
  7. 07Week 3 学习成果|异常、traceback 与 Debug 起步week-3成果
  8. 08Week 4 学习成果|Big-O 与四类基础算法week-4成果
  9. 09Week 5 学习成果|Stack、Queue 与 MinHeapweek-5成果
  10. 10Week 6 学习成果|图算法与 Python Engineering Toolkitweek-6成果