分治算法中的主定理及其应用

news2024/12/27 9:31:38

引言

学习递归算法的时候,找到了用来计算算法复杂度的主定理。问大语言模型,发现回答的主定理描述有所不同。本文比较了两个不同版本中表述的差异。并给出一些例子用来计算分治递归类算法的复杂度。

主定理的不同版本

版本1

在《算法导论》第三版第四章中,主定理的定义如下:

主定理适用于求解如下递归式算法的时间复杂度:

T ( n ) = a T ( n b ) + f ( n ) T(n) = aT\left(\frac{n}{b}\right) + f(n) T(n)=aT(bn)+f(n)

其中:

  • ( n ) 是问题规模大小;
  • ( a ) 是原问题的子问题个数;
  • ( n b ) ( \frac{n}{b} ) (bn) 是每个子问题的大小,这里假设每个子问题有相同的规模大小;
  • ( f(n) ) 是将原问题分解成子问题和将子问题的解合并成原问题的解的时间。

对于上述递归式,主定理提供了三种情况来确定时间复杂度 T ( n ) T(n) T(n)

  1. ( f ( n ) = O ( n log ⁡ b a − ϵ ) ) , ( ϵ > 0 ) ( f(n) = O(n^{\log_b a - \epsilon}) ),( \epsilon > 0) (f(n)=O(nlogbaϵ))(ϵ>0) ( T ( n ) = Θ ( n log ⁡ b a ) ) ( T(n) = \Theta(n^{\log_b a}) ) (T(n)=Θ(nlogba))
  2. f ( n ) = Θ ( n log ⁡ b a ) f(n) = \Theta(n^{\log_b a}) f(n)=Θ(nlogba),则 ( T ( n ) = Θ ( n log ⁡ b a log ⁡ n ) ) ( T(n) = \Theta(n^{\log_b a} \log n) ) (T(n)=Θ(nlogbalogn))
  3. f ( n ) = Ω ( n log ⁡ b a + ϵ ) , ϵ > 0 f(n) =\Omega(n^{\log_b a + \epsilon}) ,\epsilon > 0 f(n)=Ω(nlogba+ϵ)ϵ>0,且对于某个常数 c < 1 c < 1 c<1 和所有充分大的 n 有 a f ( n b ) ≤ c f ( n ) af\left(\frac{n}{b}\right) \leq cf(n) af(bn)cf(n),则 T ( n ) = Θ ( f ( n ) ) T(n) = \Theta(f(n)) T(n)=Θ(f(n))

版本2

问AI大模型ChatGLM有时候会给出以下回答:
主定理适用于形式如下的递归关系:

T ( n ) = a T ( n b ) + f ( n ) T(n) = aT\left(\frac{n}{b}\right) + f(n) T(n)=aT(bn)+f(n)

其中:

  • T ( n ) T(n) T(n) 是算法的时间复杂度函数。
  • a ≥ 1 a \geq 1 a1 是每次递归调用分解出的子问题的数量。
  • b > 1 b > 1 b>1 是每次递归调用时问题规模的缩小比例。
  • f ( n ) f(n) f(n) 是除了递归调用外,算法在每层递归中所做的其他工作。

主定理根据 f ( n ) f(n) f(n) n log ⁡ b a n^{\log_b a} nlogba 的关系,提供了三种情况来确定 T ( n ) T(n) T(n) 的时间复杂度:

  1. 情况1: 如果 f ( n ) = O ( n log ⁡ b a − ϵ ) f(n) = O(n^{\log_b a - \epsilon}) f(n)=O(nlogbaϵ) 对于某个常数 ϵ > 0 \epsilon > 0 ϵ>0 成立,则 T ( n ) = Θ ( n log ⁡ b a ) T(n) = \Theta(n^{\log_b a}) T(n)=Θ(nlogba)

  2. 情况2: 如果 f ( n ) = Θ ( n log ⁡ b a log ⁡ k n ) f(n) = \Theta(n^{\log_b a} \log^k n) f(n)=Θ(nlogbalogkn) 对于某个常数 k ≥ 0 k \geq 0 k0 成立,则 T ( n ) = Θ ( n log ⁡ b a log ⁡ k + 1 n ) T(n) = \Theta(n^{\log_b a} \log^{k+1} n) T(n)=Θ(nlogbalogk+1n)

  3. 情况3: 如果 f ( n ) = Ω ( n log ⁡ b a + ϵ ) f(n) = \Omega(n^{\log_b a + \epsilon}) f(n)=Ω(nlogba+ϵ) 对于某个常数 ϵ > 0 \epsilon > 0 ϵ>0 成立,并且如果 a f ( n b ) ≤ c f ( n ) af\left(\frac{n}{b}\right) \leq cf(n) af(bn)cf(n) 对于某个常数 c < 1 c < 1 c<1 和所有足够大的 n n n 成立,则 T ( n ) = Θ ( f ( n ) ) T(n) = \Theta(f(n)) T(n)=Θ(f(n))

比较这两个版本,只有情况2有所变化。版本2中f(n)可以是线性对数。而版本1中f(n)只能是多项式。所以第二个版本拓展了对数这种情况。

翻到《算法导论》第三版中的例题,给出了该拓展情况:
在这里插入图片描述

主定理的应用

1.大数乘法

Karatsuba乘法是一种快速乘法算法,由苏联数学家Anatoliy Karatsuba在1960年提出,并在1962年发表。这种算法通过递归地将大数分解为较小的数,然后进行乘法运算,减少了所需的乘法次数,从而提高了大数乘法的效率。

Karatsuba乘法的基本步骤如下:

  1. 数字分解:将两个大数 x x x y y y 分解为两部分,每部分大约是原数的一半。如果 x x x y y y 都是 n n n 位数字,则可以写为:
    x = x 1 ⋅ 1 0 m + x 0 x = x_1 \cdot 10^m + x_0 x=x110m+x0
    y = y 1 ⋅ 1 0 m + y 0 y = y_1 \cdot 10^m + y_0 y=y110m+y0
    其中 m m m 是一个正整数, m < n m < n m<n,且 $ x_0 $ 和 y 0 y_0 y0 小于 1 0 m 10^m 10m

  2. 递归乘法:通过递归地应用Karatsuba算法,计算以下三个乘积:

    • z 2 = x 1 ⋅ y 1 z_2 = x_1 \cdot y_1 z2=x1y1
    • z 0 = x 0 ⋅ y 0 z_0 = x_0 \cdot y_0 z0=x0y0
    • z 1 = ( x 1 + x 0 ) ⋅ ( y 1 + y 0 ) − z 2 − z 0 z_1 = (x_1 + x_0) \cdot (y_1 + y_0) - z_2 - z_0 z1=(x1+x0)(y1+y0)z2z0
  3. 结果合并:最后,将这三个乘积合并以得到最终结果:
    x y = z 2 ⋅ 1 0 2 m + z 1 ⋅ 1 0 m + z 0 xy = z_2 \cdot 10^{2m} + z_1 \cdot 10^m + z_0 xy=z2102m+z110m+z0

复杂度分析:

大数相乘的递归表达式

T ( n ) = { O ( 1 ) if  n = 1 3 T ( n / 2 ) + O ( n ) if  n > 1 T(n) = \begin{cases} O(1) & \text{if } n = 1 \\ 3T(n/2) + O(n) & \text{if } n > 1 \end{cases} T(n)={O(1)3T(n/2)+O(n)if n=1if n>1

  • 传统乘法的复杂度是 O ( n 2 ) O(n^2) O(n2),而Karatsuba算法的复杂度仅为 O ( n log ⁡ 2 3 ) O(n^{\log_2 3}) O(nlog23),大约是 O ( n 1.585 ) O(n^{1.585}) O(n1.585)

Python实现示例:

from math import ceil

def karatsuba(x, y):
    if x < 10 or y < 10:  # 基本情况,当x和y为个位数时
        return x * y
    n = max(len(str(x)), len(str(y)))
    m = ceil(n / 2)  # m是n的一半,向上取整
    x_H = x // (10 ** m)  # x的高半部分
    x_L = x % (10 ** m)  # x的低半部分
    y_H = y // (10 ** m)  # y的高半部分
    y_L = y % (10 ** m)  # y的低半部分
    a = karatsuba(x_H, y_H)  # 计算高半部分的乘积
    d = karatsuba(x_L, y_L)  # 计算低半部分的乘积
    e = karatsuba(x_H + x_L, y_H + y_L) - a - d  # 计算中间部分的乘积
    return int(a * (10 ** (2 * m)) + e * (10 ** m) + d)  # 合并结果

# 测试Karatsuba乘法
print(karatsuba(1234, 4321))

这种算法通过减少乘法的次数,显著提高了大数乘法的效率,尤其是在处理非常大的数字时。一般化以后有Toom-Cook乘法。

2.strassen矩阵相乘

Strassen算法是一种高效的矩阵乘法算法,由德国数学家Volker Strassen在1969年提出。它通过减少所需的乘法次数来提高矩阵乘法的效率。传统的矩阵乘法对于两个n×n的矩阵需要 n 3 n^3 n3次乘法,而Strassen算法只需要大约 n 2.81 n^{2.81} n2.81次乘法,这在大矩阵乘法中可以显著减少计算量。

Strassen算法的核心思想是将两个2×2矩阵的乘法分解为更小的子矩阵乘法,而不是直接计算四个乘积。对于两个2×2矩阵A和B,传统的乘法需要8次乘法,而Strassen算法只需要7次乘法,如下所示:

设矩阵A和B为:
A = [ a b c d ] , B = [ e f g h ] A = \begin{bmatrix} a & b \\ c & d \end{bmatrix}, \quad B = \begin{bmatrix} e & f \\ g & h \end{bmatrix} A=[acbd],B=[egfh]

传统的乘法结果矩阵C为:
C = A B = [ a e + b g a f + b h c e + d g c f + d h ] C = AB = \begin{bmatrix} ae + bg & af + bh \\ ce + dg & cf + dh \end{bmatrix} C=AB=[ae+bgce+dgaf+bhcf+dh]

Strassen算法通过以下步骤计算C:

  1. 计算七个乘积:
    M 1 = ( a + d ) ( e + h ) M_1 = (a+d)(e+h) M1=(a+d)(e+h)
    M 2 = ( b + d ) h M_2 = (b+d)h M2=(b+d)h
    M 3 = a ( f − h ) M_3 = a(f-h) M3=a(fh)
    M 4 = d ( g − e ) M_4 = d(g-e) M4=d(ge)
    M 5 = ( a + b ) e M_5 = (a+b)e M5=(a+b)e
    M 6 = ( c + d ) ( f + h ) M_6 = (c+d)(f+h) M6=(c+d)(f+h)
    M 7 = ( a − c ) ( e + f ) M_7 = (a-c)(e+f) M7=(ac)(e+f)

  2. 然后计算结果矩阵C的四个元素:
    C 11 = M 1 + M 4 − M 5 + M 7 C_{11} = M_1 + M_4 - M_5 + M_7 C11=M1+M4M5+M7
    C 12 = M 3 + M 5 C_{12} = M_3 + M_5 C12=M3+M5
    C 21 = M 2 + M 4 C_{21} = M_2 + M_4 C21=M2+M4
    C 22 = M 1 − M 2 + M 3 + M 6 C_{22} = M_1 - M_2 + M_3 + M_6 C22=M1M2+M3+M6

对于更大的矩阵,Strassen算法可以递归地应用到子矩阵上。这种方法可以减少乘法的次数,但是会增加加法和减法的次数。尽管如此,对于大规模的矩阵乘法,Strassen算法仍然可以提供显著的性能提升。

需要注意的是,Strassen算法的常数因子较大,因此在小规模矩阵上可能不如传统算法快。但是,随着矩阵规模的增加,其优势会逐渐显现。

递推表达式:
T ( n ) = 7 T ( n 2 ) + Θ ( n 2 ) T(n) = 7T\left(\frac{n}{2}\right) + \Theta(n^2) T(n)=7T(2n)+Θ(n2)

主定理(Master Theorem)是用于确定分治算法时间复杂度的一个工具。它适用于形如下列形式的递归关系:

T ( n ) = a T ( n b ) + f ( n ) T(n) = aT\left(\frac{n}{b}\right) + f(n) T(n)=aT(bn)+f(n)

其中 a ≥ 1 a \geq 1 a1 b > 1 b > 1 b>1,且 f ( n ) f(n) f(n) 是一个渐进正函数。主定理提供了一种直接的方法来确定 T ( n ) T(n) T(n) 的渐进上界,而不需要展开递归。

对于Strassen矩阵乘法,我们有递归关系:

T ( n ) = 7 T ( n 2 ) + Θ ( n 2 ) T(n) = 7T\left(\frac{n}{2}\right) + \Theta(n^2) T(n)=7T(2n)+Θ(n2)

带入到主定理中这里, a = 7 a = 7 a=7 b = 2 b = 2 b=2 f ( n ) = Θ ( n 2 ) f(n) = \Theta(n^2) f(n)=Θ(n2)

  • log ⁡ b a = log ⁡ 2 7 \log_b a = \log_2 7 logba=log27,这大约是 2.807。
  • f ( n ) = Θ ( n 2 ) f(n) = \Theta(n^2) f(n)=Θ(n2)

f ( n ) = n 2 f(n) = n^2 f(n)=n2 ,因为 2 < log ⁡ 2 7 2 < \log_2 7 2<log27。这意味着 f ( n ) f(n) f(n) 落在主定理的第三种情况

因此,根据主定理的第三种情况,我们得到:

T ( n ) = Θ ( n log ⁡ b a ) = Θ ( n log ⁡ 2 7 ) T(n) = \Theta(n^{\log_b a}) = \Theta(n^{\log_2 7}) T(n)=Θ(nlogba)=Θ(nlog27)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2251431.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【kafka03】消息队列与微服务之Kafka 读写数据

Kafka 读写数据 参考文档 Apache Kafka 常见命令 kafka-topics.sh #消息的管理命令 kafka-console-producer.sh #生产者的模拟命令 kafka-console-consumer.sh #消费者的模拟命令 创建 Topic 创建topic名为 chen&#xff0c;partitions(分区)为3&#xff0…

LuaForWindows_v5.1.5-52.exe

Releases rjpcomputing/luaforwindows GitHub #lua C:\Users\Administrator\Desktop\test.lua print("Hello lua&#xff01;") print("ZengWenFeng 13805029595")

软件无线电(SDR)的架构及相关术语

今天简要介绍实现无线电系统调制和解调的主要方法&#xff0c;这在软件定义无线电(SDR)的背景下很重要。 外差和超外差 无线电发射机有两种主要架构——一种是从基带频率直接调制到射频频率&#xff08;称为外差&#xff09;&#xff0c;而第二种超外差是通过两个调制阶段来实…

【Electron学习笔记(四)】进程通信(IPC)

进程通信&#xff08;IPC&#xff09; 进程通信&#xff08;IPC&#xff09;前言正文1、渲染进程→主进程&#xff08;单向&#xff09;2、渲染进程⇌主进程&#xff08;双向&#xff09;3、主进程→渲染进程 进程通信&#xff08;IPC&#xff09; 前言 在Electron框架中&…

Power BI - Connect to SharePoint online list with Image column

1.简单介绍 当前SharePoint online list有modern和classic两种模式&#xff0c;现在使用modern模式的比较多。list中有Image类型的列&#xff0c;Power BI如何连接到SharePoint list并显示image呢 note, SharePoint list中的Image列&#xff0c;Lookup列&#xff0c;People列…

电机控制理论基础及其应用

电机控制理论是电气工程和自动化领域中的一个重要分支&#xff0c;它主要研究如何有效地控制电机的运行状态&#xff0c;包括速度、位置、扭矩等&#xff0c;以满足各种应用需求。电机控制理论的基础知识涵盖了电机的工作原理、数学模型、控制策略以及实现技术等方面。下面是一…

二十一、QT C++

1.1QT介绍 1.1.1 QT简介 Qt 是一个跨平台的应用程序和用户界面框架&#xff0c;用于开发图形用户界面&#xff08;GUI&#xff09;应用程序以及命令行工具。它最初由挪威的 Trolltech &#xff08;奇趣科技&#xff09;公司开发&#xff0c;现在由 Qt Company 维护&#xff…

基于Java Springboot蛋糕订购小程序

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 微信…

Kubernetes 01

MESOS&#xff1a;APACHE 分布式资源管理框架 2019-5 Twitter退出&#xff0c;转向使用Kubernetes Docker Swarm 与Docker绑定&#xff0c;只对Docker的资源管理框架&#xff0c;阿里云默认Kubernetes Kubernetes&#xff1a;Google 10年的容器化基础框架&#xff0c;borg…

7. 现代卷积神经网络

文章目录 7.1. 深度卷积神经网络&#xff08;AlexNet&#xff09;7.2. 使用块的网络&#xff08;VGG&#xff09;7.3. 网络中的网络&#xff08;NiN&#xff09;7.4. 含并行连结的网络&#xff08;GoogLeNet&#xff09;7.5. 批量规范化7.5.1. 训练深层网络7.5.2. 批量规范化层…

芯片测试-射频中的单位

射频中的单位 &#x1f4a2;dB&#xff0c;dBc&#x1f4a2;&#x1f4a2;dB&#x1f4a2;&#x1f4a2;dBc&#x1f4a2;&#x1f4a2;3dB和0dB&#x1f4a2; &#x1f4a2;dBm和dBw&#x1f4a2;&#x1f4a2;dBuV&#xff0c;dBmV和dBV&#x1f4a2;&#x1f4a2;dBuV&#…

【C++】数字位数提取:从个位到十位的深入分析与理论拓展

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;第一题&#xff1a;提取个位数解法代码解法分析代码优化拓展思考&#xff1a;取模运算的普适性 &#x1f4af;第二题&#xff1a;提取十位数题目解读与思路分析方法一&…

opengl 三角形

最后效果&#xff1a; OpenGL version: 4.1 Metal 不知道为啥必须使用VAO 才行。 #include <glad/glad.h> #include <GLFW/glfw3.h>#include <iostream> #include <vector>void framebuffer_size_callback(GLFWwindow *window, int width, int heigh…

如何使用Postman优雅地进行接口自动加密与解密

引言 在上一篇文章中&#xff0c;分享了 Requests 自动加解密的方法&#xff0c;本篇文章分享一下更加方便的调试某个服务端接口。 Postman Postman 这个工具后端小伙伴应该相当熟悉了&#xff0c;一般情况下我们会在开发和逆向过程中使用它来快速向接口发送请求&#xff0c;…

PDF view | Chrome PDF Viewer |Chromium PDF Viewer等指纹修改

1、打开https://www.browserscan.net/zh/ 2、将internal-pdf-viewer改为 internal-pdf-viewer-jdtest看下效果&#xff1a; 3、源码修改&#xff1a; third_party\blink\renderer\modules\plugins\dom_plugin_array.cc namespace { DOMPlugin* MakeFakePlugin(String plugin_…

2024143读书笔记|《遇见》——立在城市的飞尘里,我们是一列忧愁而又快乐的树

2024143读书笔记|《遇见》——立在城市的飞尘里&#xff0c;我们是一列忧愁而又快乐的树 第1章 年年岁岁岁岁年年第2章 遇见第3章 有个叫“时间”的家伙走过第4章 初雪第6章 回首风烟 《华语散文温柔的一支笔&#xff1a;张晓风作品集&#xff08;共5册&#xff09;》作者张晓风…

python基础(五)

正则表达式 在编写处理字符串的程序或网页时&#xff0c;经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说&#xff0c;正则表达式就是记录文本规则的代码。 符号解释示例说明.匹配任意字符b.t可以匹配bat / but / b#t / b1t等\…

【连接池】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…

《业务流程--穿越从概念到实践的丛林》读后感一:什么是业务流程

1.4 流程建模 画流程图常见的方法派别如下: 1)流图。美国国家标准协会(ANSI)制定的规范,利用VISIO中的流程符号进行画图。 2)事件驱动流程链(EPC)。ARIS(集成信息系统架构)。认为流程是由一系列事件触发,并且 针对事件的行为又将引发新的事件,流程的表现为“事件--功…

Sybase数据恢复—Sybase数据库无法启动,Sybase Central连接报错的处理案例

Sybase数据库数据恢复环境&#xff1a; Sybase数据库版本&#xff1a;SQL Anywhere 8.0。 Sybase数据库故障&分析&#xff1a; Sybase数据库无法启动。 错误提示&#xff1a; 使用Sybase Central连接报错。 数据库数据恢复工程师经过检测&#xff0c;发现Sybase数据库出现…