首页 > 编程语言 >用主定理求解递归算法的复杂度

用主定理求解递归算法的复杂度

时间:2024-12-11 10:33:55浏览次数:3  
标签:用主 frac log 递归 复杂度 工作量 定理

主定理(Master Theorem)是一种常见于算法分析中的工具。它指出了如何解决与分治和递归有关算法的时间复杂度。


主定理

主定理的标准形式是分析以下递归式的实际复杂度:

\[T(n) = aT\left(\frac{n}{b}\right) + f(n), \]

其中:

  • \(a \geq 1\) 是递归调用的数量,表明问题被切割为几个子问题。
  • \(b > 1\) 是每次递归将问题规模缩小的因子,表明问题子问题的规模。
  • \(f(n)\) 是所有递归调用以外的额外工作量。

主定理的核心思想是比较递归的部分和非递归部分哪个增长得更快,从而决定算法的总体复杂度。根据 \(f(n)\) 的增长速度与 \(n^{\log_b a}\) 的比较,主定理分为以下三种情形:

  1. \(f(n) \in O(n^{\log_b a - \epsilon})\),某个 \(\epsilon > 0\)
    此时递归部分主导增长,时间复杂度为 \(T(n) \in \Theta(n^{\log_b a})\)。

  2. \(f(n) \in \Theta(n^{\log_b a})\)
    此时递归部分与非递归部分增长相当,时间复杂度为 \(T(n) \in \Theta(n^{\log_b a} \log n)\)。

  3. \(f(n) \in \Omega(n^{\log_b a + \epsilon})\),某个 \(\epsilon > 0\) 且 \(a f\left(\frac{n}{b}\right) \leq c f(n)\)(即递归调用的贡献足够小)
    此时非递归部分主导增长,时间复杂度为 \(T(n) \in \Theta(f(n))\)。


简单的理解

主定理的证明主要依赖于累加每一层递归所消耗的工作量。我们可以把递归的过程看作是一棵树,其中:

  • 树的每一层表示一次递归调用。
  • 每一层的总工作量由 \(a\) 个子问题的工作量 \(T(n/b)\) 和外部工作量 \(f(n)\) 构成。

对于总工作量,我们逐层分析:

树的结构

  • 第 \(k\) 层的子问题规模为 \(\frac{n}{b^k}\)。
  • 第 \(k\) 层有 \(a^k\) 个子问题,每个子问题需要的工作量为 \(f\left(\frac{n}{b^k}\right)\)。

总工作量

树的总工作量为所有层的工作量之和:

\[\text{Total Work} = \sum_{k=0}^{\log_b n} a^k f\left(\frac{n}{b^k}\right). \]

通过数学上对该式的收敛性和增长性分析证明,最终可以得出上述主定理的三种情况:

  1. 若 \(f(n)\) 增长较慢(情况 1),则递归部分占主导。
  2. 若 \(f(n)\) 和递归增长相等(情况 2),需额外乘以 \(\log n\)。
  3. 若 \(f(n)\) 增长较快且满足平衡条件(情况 3),则非递归部分占主导。

实例

二分查找

递归式为:

\[T(n) = T\left(\frac{n}{2}\right) + O(1). \]

这里:

  • \(a = 1\)(一次递归调用),
  • \(b = 2\)(问题规模缩小一半),
  • \(f(n) = O(1)\)。

根据主定理:

\[\log_b a = \log_2 1 = 0. \]

比较 \(f(n) = O(1)\) 和 \(n^0 = O(1)\),属于情况 2,因此复杂度为 \(T(n) \in \Theta(\log n)\)。

归并排序

递归式为:

\[T(n) = 2T\left(\frac{n}{2}\right) + O(n). \]

这里:

  • \(a = 2\),\(b = 2\),\(f(n) = O(n)\)。

根据主定理:

\[\log_b a = \log_2 2 = 1. \]

比较 \(f(n) = O(n)\) 和 \(n^1 = O(n)\),属于情况 2,因此复杂度为 \(T(n) \in \Theta(n \log n)\)。

Strassen 矩阵乘法

递归式为:

\[T(n) = 7T\left(\frac{n}{2}\right) + O(n^2). \]

这里:

  • \(a = 7\),\(b = 2\),\(f(n) = O(n^2)\)。

根据主定理:

\[\log_b a = \log_2 7 \approx 2.81. \]

比较 \(f(n) = O(n^2)\) 和 \(n^{2.81}\),属于情况 1,因此复杂度为 \(T(n) \in \Theta(n^{2.81})\)。


主定理的应用

主定理的思想广泛应用于算法分析,在算法分析中有许多拓展:

  1. 扩展主定理:处理一些递归项的非对称性或 \(f(n)\) 的非多项式增长形式。
  2. 递归树法:直接可视化每层的工作量,适用于无法直接套用主定理的递归式。
  3. 代入法:通过假设形式化时间复杂度并验证其成立性来解决递归式。

主定理要求递归式严格符合标准形式,对于不符合形式的递归式(如非均匀分割),还需要其他方法分析。另外,主定理只指出了 \(f(n)\) 的一部分情况,若 \(f(n)\) 的条件复杂(如渐进有界性),主定理在一些复杂问题中可能较难满足条件,还需要其他工具。

标签:用主,frac,log,递归,复杂度,工作量,定理
From: https://www.cnblogs.com/ofnoname/p/18598818

相关文章

  • RAG分块策略:主流方法(递归、jina-seg)+前沿推荐(Meta-chunking、Late chunking、SLM-SFT)
    RAG分块策略:主流方法(递归、jina-seg)+前沿推荐(Meta-chunking、Latechunking、SLM-SFT)大多数常用的数据分块方法(chunking)都是基于规则的,采用fixedchunksize(译者注:将数据或文本按照固定的大小进行数据分块)或overlapofadjacentchunks(译者注:让相邻的数据块具有重叠内容,确保信......
  • 【数据结构与算法】回溯算法:LeetCode“排列问题” 求解,解释并模拟递归+回溯的遍历过程
      【作者自述:记录学习笔记,既然写了就让更多的人看到吧!欢迎大家关注交流学习,一步一个脚印持续更新!】【更多推荐笔记】【数据结构与算法】动态规划:解密“完全背包问题”的真相!附LeetCode四大问题的实现-CSDN博客【数据结构与算法】动态规划:解密“0-1背包问题”的真相!附LeetC......
  • 了解JS递归
    在JavaScript中,递归是一个非常重要的概念,它允许函数在其定义内部调用自身。递归在处理许多类型的问题时非常有用,尤其是那些可以通过分解成更小、更简单的子问题来解决的问题。然而,递归也需要谨慎使用,因为它可能导致堆栈溢出(特别是当递归调用非常深时)。以下是关于JavaScript递......
  • 写一个单向链数据结构的 js 实现并标注复杂度
    classNode{constructor(data){this.data=data;this.next=null;}}classLinkedList{constructor(){this.head=null;this.size=0;//Keeptrackofthelistsize}//Addanewnodetotheendofthelist(append)......
  • 递归和分治
    一.递归的概念一个递归过程表示为基语句和终止条件。递归算法的思想是将较大规模的对象的操作归结为对较小规模的对象实施同样的操作。将复杂问题分解为较为简单的子问题组合。举例:单链表是一种递归的数据结构,hanoi问题是一种递归的问题求解。优点:结构清晰可读性强,容易用数......
  • AcWing 92. 递归实现指数型枚举
    文章目录前言代码思路前言简单题只有那么一些,后面的稍微难一点点的题,自己写一道可能就要一个小时。现在不写之后需要的时候可能就来不及了。好吧。种一棵树最好的时间是十年前,对,假设我十年之前是信息竞赛选手,把这些题刷得非常熟练,现在可能就不需要写这些算法题了,但是......
  • 初探C语言|浅谈函数的递归
    文章目录1.什么是递归?2.递归的两个必要条件代码示例3.两个例题(阶乘和斐波那契)发现问题为什么呢?stackoverflow(栈溢出)常规写法(迭代)4.递归与迭代相比较欢迎讨论:如有错误或不足,欢迎指正和建议,本人主打“听劝”。当然,如有疑问,也期待你在评论区留言互动。点赞+关注:如果......
  • 递归疑难问题解答
    1.计算一个数的每位之和(递归实现)写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和例如,调用DigitSum(1729),则应该返回1+7+2+9,它的和是19输入:1729,输出:19#include<stdio.h>intfac(intn){ if(n<10) { returnn; } else { returnfac(n/10)+......
  • 【唐叔学算法】第二天:探索递归的魅力
    递归算法简介递归算法是一种在解决问题时,将问题分解成更小的、相似的子问题来解决的方法。它是一种非常强大的编程技术,尤其适用于那些可以自然分解为相似子问题的场景。递归算法的核心思想是:问题可以分解为更小的相同问题,直到问题足够小以至于可以直接解决。如何使用递归......
  • 关于二叉树的先/中/后序的非递归遍历
    力扣上有原题~中 先后前言先前跟着acwing学习算法基础课,自以为已经掌握了基础的算法和数据结构,剩下就差做题了,结果之后在力扣和洛谷上看到有关二叉树的题目,完全不知道是怎么一回事,故开始二叉树的学习(果然学习数据结构基础不能光看课)正文本片文章主要讲述二叉树的先中后......