CPH-第八章 均摊分析

均摊分析思想:针对单次操作耗时不均、但整体操作总次数可控的算法,不纠结单次操作的最坏复杂度,而是估算全部操作的总时间开销,证明平均到每次操作的复杂度足够低。

  • 很多算法单次操作看似耗时很高,但从全局看每个元素只会被处理有限次。
  • 双指针、单调栈、单调队列都是这一思想的典型产物,是处理数组问题的高频高效技巧。

8.1 双指针法(Two pointers method)

核心思想

  • 用两个指针遍历数组,两个指针都只向单一方向移动(不会回退),因此每个指针在整个算法过程中最多移动 \(n\) 步,总操作量为 \(O(n)\),均摊到每一步都是常数时间。

子数组和问题

  • 给定全为正整数的数组和目标和 \(x\),判断是否存在连续子数组的和恰好等于 \(x\)。

    • 算法流程:维护左右指针表示子数组区间;左指针每向右移动一步,右指针就尽可能向右延伸,只要子数组和不超过 \(x\)。若和恰好等于 \(x\) 则找到解。
    • 复杂度分析:右指针全程只向右不向左,总移动步数不超过 \(n\);左指针也仅移动 \(n\) 步。因此总时间复杂度为 \(O(n)\)。

2SUM 问题

  • 给定数组和目标和 x,找出两个元素使其和为 x。
    • 先将数组排序,左指针指向数组开头、右指针指向数组末尾;
    • 左指针逐步右移,右指针同步左移,使两数之和向目标值靠近。
  • 复杂度分析:排序耗时 \(O(n \log n)\),双指针遍历耗时 \(O(n)\),整体复杂度 \(O(n \log n)\)。
  • 延伸:基于相同思想,3SUM 问题可以在 \(O(n^2)\) 时间内求解。

8.2 最近更小元素(Nearest smaller elements)

  • 对数组中每个元素,找到它左侧第一个比它小的元素(不存在则标记为空)。

  • 算法:单调栈

    • 从左到右遍历数组,维护一个元素值单调递增的栈。

    • 不断弹出栈顶所有大于等于当前元素的元素。

    • 此时栈顶元素就是当前元素的「最近更小元素」。

    • 将当前元素压入栈中。

  • 均摊复杂度分析

    • 每个数组元素恰好入栈一次、最多出栈一次,整个算法过程中栈的弹出操作总次数不超过 \(n\)。

    • 因此尽管单次遍历可能弹出多个元素,但全部操作总次数为 \(O(n)\),均摊时间复杂度为 \(O(n)\)。

8.3 滑动窗口最小值(Sliding window minimum)

  • 固定大小的窗口从数组左端向右滑动,输出每个窗口位置对应的最小值。

  • 算法:单调队列

    • 维护一个元素值单调递增的双端队列,队首始终是当前窗口的最小值:
    • 窗口右移加入新元素时,从队尾不断弹出所有大于等于新元素的元素,再将新元素加入队尾;
    • 检查队首元素是否已滑出窗口,若滑出则从队首移除;
    • 此时队首元素即为当前窗口的最小值。
  • 均摊复杂度分析

    • 每个元素恰好入队一次、最多出队一次,所有入队、出队操作的总次数为 \(O(n)\)。
    • 因此算法整体均摊时间复杂度为 \(O(n)\)。
posted @ 2026-10-30 14:10  LifeLotus  阅读(4)  评论(0)    收藏  举报