递归函数时间复杂度分析

递归函数时间复杂度分析

 

(1) 递归执行过程 
   例子:求N!。 
    这是一个简单的"累乘"问题,用递归算法也能解决。 
    n! = n * (n - 1)!   n > 1 
    0! = 1, 1! = 1      n = 0,1 
    因此,递归算法如下: 
   
Java代码 
fact(int n) {  
    if(n == 0 || n == 1)   
         return 1;  
        else   
             return n * fact(n - 1);  
    }  
    以n=3为例,看运行过程如下: 
    fact(3) ----- fact(2) ----- fact(1) ------ fact(2) -----fact(3) 
    ------------------------------>  ------------------------------> 
                递归                            回溯 
  递归算法在运行中不断调用自身降低规模的过程,当规模降为1,即递归到fact(1)时,满足停止条件停止递归,开始回溯(返回调用算法)并计算,从fact(1)=1计算返回到fact(2);计算2*fact(1)=2返回到fact(3);计算3*fact(2)=6,结束递归。 
   算法的起始模块也是终止模块。 
(2) 递归实现机制 
    每一次递归调用,都用一个特殊的数据结构""记录当前算法的执行状态,特别地设置地址栈,用来记录当前算法的执行位置,以备回溯时正常返回。递归模块的形式参数是普通变量,每次递归调用得到的值都是不同的,他们也是由""来存储。 
(3) 递归调用的几种形式 
    一般递归调用有以下几种形式(其中a1a2b1b2k1k2为常数)。 
   <1> 直接简单递归调用: f(n) {...a1 * f((n - k1) / b1); ...}; 
    
   <2> 直接复杂递归调用: f(n) {...a1 * f((n - k1) / b1); a2 * f((n - k2) / b2); ...}; 
    <3> 间接递归调用:  f(n) {...a1 * f((n - k1) / b1); ...}, 
                        g(n) {...a2 * f((n - k2) / b2); ...}。 
2. 递归算法效率分析方法 
   递归算法的分析方法比较多,最常用的便是迭代法。 
  迭代法的基本步骤是先将递归算法简化为对应的递归方程,然后通过反复迭代,将递归方程的右端变换成一个级数,最后求级数的和,再估计和的渐进阶。 
  <1> 例:n! 
       算法的递归方程为: T(n) = T(n - 1) + O(1); 
       迭代展开: T(n) = T(n - 1) + O(1) 
                       = T(n - 2) + O(1) + O(1) 
                       = T(n - 3) + O(1) + O(1) + O(1) 
                       = ...... 
                       = O(1) + ... + O(1) + O(1) + O(1) 
                       = n * O(1) 
                       = O(n) 
      这个例子的时间复杂性是线性的。 
<2> 例:如下递归方程: 
      
      T(n) = 2T(n/2) + 2, 且假设n=2k次方。 
      T(n) = 2T(n/2) + 2 
           = 2(2T(n/2*2) + 2) + 2 
           = 4T(n/2*2) + 4 + 2 
           = 4(2T(n/2*2*2) + 2) + 4 + 2 
           = 2*2*2T(n/2*2*2) + 8 + 4 + 2 
           = ... 
           = 2(k-1)次方 * T(n/2(i-1)次方) + $(i:1~(k-1))2i次方 
           = 2(k-1)次方 + (2k次方)  - 2 
           = (3/2) * (2k次方) - 2 
           = (3/2) * n - 2 
           = O(n) 
      这个例子的时间复杂性也是线性的。 
<3> 例:如下递归方程: 
      
      T(n) = 2T(n/2) + O(n), 且假设n=2k次方。 
      T(n) = 2T(n/2) + O(n) 
           = 2T(n/4) + 2O(n/2) + O(n) 
           = ... 
           = O(n) + O(n) + ... + O(n) + O(n) + O(n) 
           = k * O(n) 
           = O(k*n) 
           = O(nlog2n) //2为底 
     
      一般地,当递归方程为T(n) = aT(n/c) + O(n), T(n)的解为: 
      O(n)          (a<c && c>1) 
      O(nlog2n)     (a=c && c>1) //2为底 
      O(nlogca)     (a>c && c>1) //n(logca)次方,以c为底 
   上面介绍的3种递归调用形式,比较常用的是第一种情况,第二种形式也有时出现,而第三种形式(间接递归调用)使用的较少,且算法分析 
比较复杂。 下面举个第二种形式的递归调用例子。 
  <4> 递归方程为:T(n) = T(n/3) + T(2n/3) + n 
     为了更好的理解,先画出递归过程相应的递归树: 
                            n                        --------> n 
                    n/3            2n/3              --------> n 
              n/9       2n/9   2n/9     4n/9         --------> n 
           ......     ......  ......  .......        ...... 
                                                     -------- 
                                                     总共O(nlogn) 
     累计递归树各层的非递归项的值,每一层和都等于n,从根到叶的最长路径是: 
    
      n --> (2/3)n --> (4/9)n --> (12/27)n --> ... --> 1 
     设最长路径为k,则应该有: 
      
     (2/3)k次方 * n = 1 
     得到 k = log(2/3)n  // (2/3)为底 
     于是 T(n) <= (K + 1) * n = n (log(2/3)n + 1) 
     即 T(n) = O(nlogn) 
    由此例子表明,对于第二种递归形式调用,借助于递归树,用迭代法进行算法分析是简单易行的。

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

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

相关文章

Dubbo 3 StateRouter:下一代微服务高效流量路由

目前的微服务架构中&#xff0c;通常包含服务消费者、服务提供者、注册中心、服务治理四元素&#xff0c;其中服务消费者会向注册中心获取服务提供者的地址列表&#xff0c;并根据路由策略选出需要调用的目标服务提供者地址列表&#xff0c;最后根据负载算法直接调用提供者。当…

首次全面解析云原生成熟度模型:解决企业「诊断难、规划难、选型难」问题

从“上云”到“云上”原生&#xff0c;云原生提供了最优用云路径&#xff0c;云原生的技术价值已被广泛认可。当前行业用户全面转型云原生已是大势所趋&#xff0c;用户侧云原生平台建设和应用云原生化改造进程正在加速。 然而&#xff0c;云原生复杂的技术栈和传统IT的历史包…

有效预警6要素:亿级调用量的阿里云弹性计算SRE实践

编者按&#xff1a;随着分布式系统和业务需求的飞速发展&#xff0c;监控告警在我们保障系统稳定性和事故快速恢复的全周期中都是至关重要的。9月3号&#xff0c;阿里云弹性计算管控SRE李成武老师(花名佐井)&#xff0c;受「TakinTalks稳定性社区」邀请&#xff0c;在线分享日常…

SSE指令集入门

Intel公司的单指令多数据流式扩展&#xff08;SSE&#xff0c;Streaming SIMD Extensions&#xff09;技术能够有效增强CPU浮点运算的能力。Visual Studio .NET 2003提供了对SSE指令集的编程支持&#xff0c;从而允许用户在C代码中不用编写汇编代码就可直接使用SSE指令的功能。…

浮点运算是什么?

简单说就是小数的加减乘除运算。 在计算机的硬件中是没有小数点这个东西的。cpu能处理的东西都是整的。所以&#xff0c;小数就要用类似科学计数法的方式来表示。如1.234在计算机里面&#xff0c;可以理解成用1234和-3两个整数来表示1234*10的-3次方&#xff0c;这类数就叫浮点…

CISC与RISC的区别?

CISC是指复杂指令系统计算机&#xff08;Complex Instruction Set Computer&#xff09;&#xff1b;RISC是指精简指令系统计算机&#xff08;Reduced Instruction Set Computer&#xff09;。这里的 计算机指令系统 指的是计算机的最低层的 机器指令 &#xff0c;也就是CPU能够…

EMR 重磅发布智能运维诊断系统(EMR Doctor)——开源大数据平台运维利器

大数据运维的挑战—如何保证集群稳定与运行效率 企业级大数据集群通常拥有海量的数据存储、日常运算成干上万的计算任务&#xff0c;需要满足各类上层业务的计算需求。对于这类集群的运维往往充满着挑战&#xff1a;海量的数据、庞杂的组件以及组件之间复杂的依赖关系、对于时…

DP为王——动态规划法学习笔记

动态规划英文名Dynamic Programming&#xff0c;这个名称总让人有一种时曾相识的感觉&#xff0c;可能是因为容易和“线性规划”之类的概念搞混。 首先&#xff0c;适用动态规划的问题十分广泛和常见——地图路径搜索&#xff08;深度优先、广度优先、A*&#xff09;&#xff0…

从中间件到分布式数据库,PolarDB-X 的透明之路

PolarDB-X前身是淘宝内部使用的分库分表中间件TDDL&#xff08;2007年&#xff0c;Java库的形态&#xff09;&#xff0c;早期以DRDS&#xff08;2012年开始研发&#xff0c;2014年上线&#xff0c;分库分表中间件MySQL Proxy的形态&#xff09;的品牌在阿里云上提供服务&#…

阿里云EMAS 移动测试,帮您快速掌握移动端兼容性测试技巧

一、兼容性测试可以查到哪些问题 界面适配问题&#xff0c;确定是否能正常安装、启动。各个页面潜在的崩溃、无响应等问题。应用性能问题&#xff0c;例如启动时间、页面加载时间、功耗等。 二、阿里云兼容性测试工具的功能优势 提供在线录制功能&#xff0c;可视化录制出功能…

零信任策略下K8s安全监控最佳实践(K+)

云原生架构新风险与需求概述 安全风险概述 传统的网络安全架构理念是基于边界的安全架构&#xff0c;企业构建网络安全体系时&#xff0c;首先要做的是寻找安全边界&#xff0c;把网络划分为外网、内网等不同的区域&#xff0c;然后在边界上部署防火墙、入侵检测、WAF等产品。…

ATC‘22顶会论文RunD:高密高并发的轻量级 Serverless 安全容器运行时

编者按&#xff1a;目前的安全容器软件栈 — 包括 host 操作系统中的 cgroup、guest 操作系统和用于函数工作负载的容器 rootfs&#xff0c;都会导致低部署密度和在低并发能力。为此&#xff0c;RunD 作为一种轻量级安全容器运行时&#xff0c;提出了 host-to-guest 的全栈优化…

getline函数

getline&#xff08;istream &in, string &s&#xff09; 从输入流读入一行到string s •功能&#xff1a;–从输入流中读入字符&#xff0c;存到string变量–直到出现以下情况为止&#xff1a;•读入了文件结束标志•读到一个新行•达到字符串的最大长度–如果getline…

Dubbo Mesh:从服务框架到统一服务控制平台

Apache Dubbo 是一款 RPC 服务开发框架&#xff0c;用于解决微服务架构下的服务治理与通信问题&#xff0c;官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力&#xff0c; 利用 Dubbo 提供的丰富服务治理特性&…

struct和typedef struct彻底明白了

struct和typedef struct 分三块来讲述&#xff1a;   1 首先&#xff1a;//注意在C和C里不同     在C中定义一个结构体类型要用typedef:     typedef struct Student     {     int a;     }Stu;     于是在声明变量的时候就可&#xff1a;Stu stu1;…

智能搜索引擎 | 驱动电商业务增长实践

开放搜索是阿里集团搜索业务中台&#xff0c;基于大数据深度学习在线服务体系打造的智能搜索云服务产品。拥有核心引擎、召回排序、搜索引导、充分开放等核心能力&#xff0c;可应用在电商行业、教育行业、内容行业等场景。目前帮助数千家客户搭建自己的搜索业务。 实践案例&a…

c++ map 函数

cMap是STL的一个关联容器&#xff0c;它提供一对一&#xff08;其中第一个可以称为关键字&#xff0c;每个关键字只能在map中出现一次&#xff0c;第二个可能称为该关键字的值&#xff09;的数据处理能力&#xff0c;由于这个特性&#xff0c;它完成有可能在我们处理一对一数据…

通过 Jenkins 构建 CI/CD 实现全链路灰度

本文介绍通过 Jenkins 构建流水线的方式实现全链路灰度功能。在发布过程中&#xff0c;为了整体稳定性&#xff0c;我们总是希望能够用小部分特定流量来验证下新发布应用是否正常。 即使新版本有问题&#xff0c;也能及时发现&#xff0c;控制影响面&#xff0c;保障了整体的稳…

合阔智云核心生产系统切换到服务网格 ASM 的落地实践

背景 合阔智云(http://www.hexcloud.cn) 是专注于为大中型零售连锁行业&#xff0c;提供全渠道业务中/前台产品和解决方案&#xff0c;并建立以消费者为中心的全渠道交易和敏捷供应链的新一代零售运营协同平台。 合阔智云提供了从全渠道交易管理到订单履约再到门店供应链完整…

Serverless 架构下的 AI 应用开发:入门、实战与性能优化

随着时间的推移&#xff0c;Serverless 架构变得越来越火热&#xff0c;凭借着极致弹性、按量付费、低成本运维等特性&#xff0c;在很多领域发挥着越来越重要的作用&#xff1b;机器学习领域在近些年也非常火热&#xff0c;并在越来越多的行业中得到应用。 实际上&#xff0c…