算法--递归--走台阶问题(2种递归+递归改循环)

文章目录

    • 递归:
      • 注意事项:
    • 问题1
            • 思路
            • 1.递归代码(未考虑重复计算问题)
            • 2.循环代码
            • 3.递归代码(避免重复计算问题)
            • 测试运行时间
    • 问题2

递归:

一个问题可以分解成若干子问题,且求解思路一样,当到一定的情况下有终止条件,这样的问题可以用递归方法求解

注意事项:

  1. 递归调用深度太大,栈空间会耗尽溢出
  2. 注意避免调用中某些值的重复计算(见以下代码3)
  3. 递归,频繁调用函数,时间成本高(见以下代码1)
  4. 递归代码可以改成循环代码 (见以下代码2)

问题1

给你 n 个台阶,你的最大步幅是2步,可以一次走1步,也可以一次走2步,问有多少种走法?

思路
  1. 假设总共走法为 f (n) ,我现在走1步,后面还有 n-1 步(其走法为 f (n-1) )
  2. 我还可以,开始走2步,后面还有 n-2 步(其走法为 f(n-2) )
  3. 那么递推公式即: f (n) = f (n-1) + f (n-2)
  4. 终止条件:f (1) = 1; f (2) = 2;
1.递归代码(未考虑重复计算问题)

以下所有代码原来采用 size_t 溢出,改用 unsigned long

#include <iostream>
using namespace std;
unsigned long cal(unsigned long n)
{if(n==1)return 1;else if(n==2)return 2;return cal(n-1)+cal(n-2);
}
int main()
{size_t n;cout << "请输入你要走的台阶数 n :" ;cin >> n;cout << "走台阶有 " << cal(n) << " 种方案。" << endl;return 0;
}

以上递归方法,在 n 比较小的时候运行时间较短
输入 n = 100 时,超过10s还没出结果,我就终止程序了。以下改用循环。

2.循环代码
#include <iostream>
using namespace std;
int main()  //循环
{unsigned long n, step, nextStep = 2, nextnextStep = 1;cout << "请输入你要走的台阶数 n :" ;cin >> n;if(n > 0){if(n == 1){step = 1;} else if(n == 2){step = 2;}else{for(int i = 2; i < n; ++i){step = nextStep + nextnextStep;nextnextStep = nextStep;nextStep = step;}}cout << "走台阶有 " << step << " 种方案。" << endl;}return 0;
}

输入 n = 100 时,改用循环,眨眼间出结果。

在这里插入图片描述

3.递归代码(避免重复计算问题)

代码 1 中的 f(n), 比如 n = 5 时
在这里插入图片描述
以下代码,屏蔽多次计算重复的值

#include <iostream>
#include <iterator>
#include <map>
using namespace std;
unsigned long cal(unsigned long n, map<unsigned long, unsigned long>& n_fn_map)
{map<unsigned long,unsigned long>::iterator iter = n_fn_map.find(n);   //查找key nif(iter != n_fn_map.end()){return iter->second;    //如果找到了,就不必进行下面计算了,直接返回value}if(n==1){n_fn_map.insert(pair<unsigned long, unsigned long>(1,1)); //把f(1)存入映射return 1;}else if(n==2){n_fn_map.insert(pair<unsigned long, unsigned long>(2,2)); //把f(2)存入映射return 2;}else{size_t sum = cal(n-1,n_fn_map)+cal(n-2,n_fn_map);   //递归调用函数n_fn_map.insert(pair<unsigned long, unsigned long>(n,sum));       //求得的f(n)存入映射,供后面查询直接使用return sum;}
}
int main()  //递归(带避免重复计算fn的值功能)
{size_t n;cout << "请输入你要走的台阶数 n :" ;cin >> n;map<unsigned long, unsigned long> n_Fn;   //n,f(n)的 k,v 容器cout << "走台阶有 " << cal(n,n_Fn) << " 种方案。" << endl;return 0;
}

输入 n = 100,程序也是眨眼间出结果
在这里插入图片描述

测试运行时间

测试程序运行时间shell代码:https://blog.csdn.net/qq_21201267/article/details/81840299
在这里插入图片描述

问题2

给你 n 个台阶,你的最大步幅是2步,可以一次走1步,也可以一次走2步,先迈左脚,要求最后到达时是右脚,问有多少种走法?

解法1:模拟实际的行走,暴力搜索

/**1. @description: 39个台阶,一次走1步或2步,左脚出发,要求右脚到达2. @author: michael ming3. @date: 2019/4/6 18:174. @modified by: */
#include <iostream>
using namespace std;
void recursion(const unsigned long &targetStairs, unsigned long steps, unsigned long stairsWalkAway, unsigned long &ways)
{		//暴力搜索,n很大时效果不好if(stairsWalkAway > targetStairs)	//走过了,不做记录return;else if(stairsWalkAway == targetStairs && steps%2 == 0)	//正好走到,且步数为偶数(右脚到达){ways++;	//记录一种方案可以return;}else	//没走到,继续递归{recursion(targetStairs, steps+1, stairsWalkAway+1, ways);recursion(targetStairs, steps+1, stairsWalkAway+2, ways);}
}
int main()
{unsigned long stairs = 0, steps = 0, stairsWalkAway = 0, ways = 0;cout << "请输入台阶个数:" << endl;cin >> stairs;recursion(stairs, steps, stairsWalkAway, ways);cout << "左脚出发,右脚到达的方案有:" << ways << " 种。" << endl;return 0;
}

解法2:递推公式和之前一样,结束条件变了

  1. n = 2 时,不论什么情况,大家都只有1种可能,使得右脚到达,f (2) = 1
  2. n = 1时,只剩1步了,如果已经走过了偶数步,那就是不可能右脚达到,f(1) = 0;如果已走过奇数步,那也只有1种可能,右脚到达,f(1) = 1
  3. 由于 f(1) 是变化的,所以不能用上面问题1的代码3那种方法存储 f(n) 的值,因为其都与 f(1) 相关。所以当 n 比较大的时候还没有找到好的解决办法。
#include <iostream>
#include <map>
using namespace std;
unsigned long cal(size_t n,  size_t stepWalkAway)
{if(n==1){if(stepWalkAway%2 == 0)return 0; //只剩1步了,如果走过了偶数步,那就是右脚达到,不可能了,0return 1;}else if(n==2)   //n = 2 时,不论什么情况,大家都只有1种可能,使得右脚到达{return 1;}else{return cal(n-1,stepWalkAway+1)+cal(n-2,stepWalkAway+1);   //递归调用函数}
}
int main()  
{size_t n, stepWalkAway = 0;cout << "请输入你要走的台阶数 n :" ;cin >> n;cout << "左脚开走,右脚走到有 " << cal(n,stepWalkAway) << " 种方案。" << endl;return 0;
}

在这里插入图片描述
解法3:动态规划,现在还不太明白
见他人博客:
https://blog.csdn.net/qq_40269087/article/details/80236102
大概的思路是:自底向上

  • 用 left [ i ] 表示剩余 i 个台阶,左脚到达的可能方案, right [ i ] 表示右脚到达的方案
  • 边界条件: left [ 1 ] = 1; left [ 2 ] = 1; right [ 1 ] = 0; right [ 2 ] = 1
  • 现在还有3个台阶到达,相当于在前面到达的方案中,退一步(1个台阶或者2个台阶),那么我在剩余3个台阶时,左脚到达 left [ 3 ] = right [ 2 ] + right [ 1 ] ;(右脚可以到达的方案,后退一步就变成了左脚到达的方案)
  • 同理 right [ 3 ] = left [ 2 ] + left [ 1 ]
#include <iostream>
using namespace std;
unsigned long dynamicProgram(size_t N)
{unsigned long left[N+1], right[N+1];left [1] = 1; left [2] = 1; right [1] = 0; right [2] = 1;for(size_t i = 3; i <= N; ++i){left[i] = right[i-1] + right[i-2];right[i] = left[i-1] + left[i-2];}return right[N];    //题目要求返回右脚到达方案
}
int main()
{size_t N;cout << "请输入你要走的台阶数 n :" ;cin >> N;cout << "左脚开走,右脚走到有 " << dynamicProgram(N) << " 种方案。" << endl;return 0;
}

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

最新2019 蚂蚁金服4面(Java)面试题

蚂蚁金服Java一面 1 自我介绍和项目 2 Java的内存分区 3 Java对象的回收方式&#xff0c;回收算法。 4 CMS和G1了解么&#xff0c;CMS解决什么问题&#xff0c;说一下回收的过程。 5 CMS回收停顿了几次&#xff0c;为什么要停顿两次。 6 Java栈什么时候会发生内存溢出&…

论文浅尝 | 基于表示学习的大规模知识库规则挖掘

链接&#xff1a;www.ict.griffith.edu.au/zhe/pub/OmranWW18.pdf动机传统的规则挖掘算法因计算量过大等原因无法应用在大规模KG上。为了解决这个问题&#xff0c;本文提出了一种新的规则挖掘模型RLvLR(Rule Learning via LearningRepresentation)&#xff0c;通过利用表示学习…

深度学习推荐系统中各类流行的Embedding方法

Embedding技术概览&#xff1a;对其它Embedding技术不熟悉&#xff0c;可以看我的上一篇文章&#xff1a;深度学习推荐系统中各类流行的Embedding方法&#xff08;上&#xff09;Graph Embedding简介Word2Vec和其衍生出的Item2Vec类模型是Embedding技术的基础性方法&#xff0c…

超强干货!7个腾讯最常用的用户研究方法

超强干货&#xff01;7个腾讯最常用的用户研究方法调查知识2017-09-19每天都有互联网产品上市&#xff0c;人们电脑上、手机上的应用在短期之内就可能增增减减换了很多波&#xff0c;最终留下的、那些最经典的产品&#xff0c;都是以好的体验设计取胜。这些产品或许看似很“简单…

算法--递归--汉诺塔问题

文章目录1. 问题分析2. 面试题1. 问题分析 游戏规则&#xff1a;一次只能挪一片&#xff1b;小的只能在大的上面&#xff1b;把所有的从A柱挪到C柱。 递推公式&#xff1a; 上部 n - 1 个 A 到 B&#xff1b;最底下 1 个 A 到 C &#xff1b;上部 n - 1 个 B 到 C&#xff1b;…

论文浅尝 | 面向跨语言实体对齐的知识图谱与实体描述协同嵌入方法

来源: IJCAI2018链接: https://www.ijcai.org/proceedings/2018/0556.pdf动机近年来&#xff0c;随着多语言知识图谱嵌入(Multilingual KG embedding)的研究&#xff0c;实体的潜在语义表示以及跨语言知识推理等任务均取得一定成效&#xff0c;因此也推动了许多知识驱动的跨语言…

最新阿里聚划算Java 5轮面试题,涵盖GC收集器、多线程锁等

一面 详细的介绍JVM的内存模型结构 JVM最常用的参数配置讲讲 GC垃圾收集算法、GC垃圾收集器有哪些&#xff0c;以及新生代老生代 分别用什么算法 多线程的几种加锁方式详细介绍 实现线程安全的方式&#xff1f;ThreadLocal原理&#xff1f;线程池了解吗说说看&#xff1f;自…

2004-2019十六年热点事件库HistoryHotEventBase项目

HistoryHotEventBase historyhotevent projrct ,which concentrate on the dayily hot event covers the time range from 2004 to 2019, 16 years in total&#xff0c;从2004年至2019年共16年的每日热点事件项目&#xff0c;目标包括构建起从2004年至今共16年的历时热点标题数…

OSI七层模型详解-开放系统互联参考模型详解

原文链接&#xff1a;https://blog.csdn.net/yaopeng_2005/article/details/7064869 OSI 七层模型通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯&#xff0c;因此其最主要的功能就是帮助不同类型的主机实现数据传输 。 完成中继功能的节点通常称为中继系…

最新天猫Java3轮面试题目:虚拟机+并发锁+Sql防注入+Zookeeper

天猫一面 自我介绍、项目介绍 Spring拦截器、实现了哪些方法&#xff1f;底层原理 AOP如何配置&#xff0c;底层原理、2种动态代理&#xff0c;aop注解实现&#xff0c;xml定义切面 Bean的作用域&#xff0c;单例模式是否线程安全&#xff1f;恶汉模式是否线程安全&#xff…

NLP中的少样本困境问题探究

一只小狐狸带你解锁 炼丹术&NLP 秘籍作者&#xff1a;JayLou娄杰&#xff08;NLP算法工程师&#xff0c;信息抽取方向&#xff09;前言在医疗、金融、法律等领域&#xff0c;高质量的标注数据十分稀缺、昂贵&#xff0c;我们通常面临少样本低资源问题。本文从「文本增强」和…

军事武器知识图谱构建与自动问答项目QAonMilitaryKG

QAonMilitaryKG QAonMilitaryKG&#xff0c;QaSystem based on military knowledge graph that stores in mongodb which is different from the previous one, 基于mongodb存储的军事领域知识图谱问答项目&#xff0c;包括飞行器、太空装备等8大类&#xff0c;100余小类&#…

python--从入门到实践--chapter 9 类

类的定义格式&#xff1a; class Name(Father_class):def __init__(self, para, ...):self.para xdef __init__(self, para, ...):super().__init__(para, ...) #调用父类的构造函数class Car():def __init__(self,make,model,year): #构造函数self.make makeself.model mo…

连载 | 知识图谱发展报告 2018 -- 前言

OpenKG 将开始连载《知识图谱发展报告(2018)》&#xff0c;希望该连载能够让更多的人深入了解知识图谱。欢迎各位读者留言讨论。1. 知识图谱的研究目标与意义 知识图谱&#xff08;Knowledge Graph&#xff09;以结构化的形式描述客观世界中概念、实体及其关系&#xff0c;将互…

网址(url),域名,ip地址,dns,hosts之间的关系

网址&#xff08;url&#xff09;&#xff0c;域名&#xff0c;ip地址&#xff0c;dns&#xff0c;hosts之间的关系 什么是ip&#xff1f; 我们知道&#xff0c;在Internet上有千百万台主机&#xff0c;为了区分这些主机&#xff0c;人们给每台主机都分配了一个专门的地址&…

事理图谱概念辨析及其与风险标签分类结合的应用探讨

以事件为描述核心&#xff0c;以揭示事件之间的演化逻辑关系的事理图谱自提出后&#xff0c;引起了工业界的极大兴趣&#xff0c;在积极探索事理图谱本质、事理图谱构建技术细节的同时&#xff0c;如何找到技术与应用场景之间的结合成为目前广泛讨论的问题。我们团队持续对以上…

一篇文章带你熟悉 TCP/IP 协议(网络协议篇二)

涤生_Woo2017年11月11日阅读 15544关注一篇文章带你熟悉 TCP/IP 协议&#xff08;网络协议篇二&#xff09;同样的&#xff0c;本文篇幅也比较长&#xff0c;先来一张思维导图&#xff0c;带大家过一遍。一图看完本文一、 计算机网络体系结构分层计算机网络体系结构分层计算机网…

PyTorch数据Pipeline标准化代码模板

前言PyTorch作为一款流行深度学习框架其热度大有超越TensorFlow的感觉。根据此前的统计&#xff0c;目前TensorFlow虽然仍然占据着工业界&#xff0c;但PyTorch在视觉和NLP领域的顶级会议上已呈一统之势。这篇文章笔者将和大家聚焦于PyTorch的自定义数据读取pipeline模板和相关…

2019 最全支付宝高级Java现场面试37题

支付宝现场三面面试题目,文末有福利&#xff1a;阿里经典面试88题目答案 01 支付宝一面 介绍一下自己。 项目参与的核心设计有哪些 ArrayList和LinkedList底层 HashMap及线程安全的ConcurrentHashMap&#xff0c;以及各自优劣势 Java如何实现线程安全 Synchronized和Lock…

腾讯互娱刘伟 | 知识图谱在运维中的应用

本文转载自公众号&#xff1a;InfoQ。随着业务监控建设不断完善&#xff0c;海量业务故障时产生成百上千条告警&#xff0c;如何智能定位故障根源、实时统计业务影响是现阶段运营面临的一个难题。Google 利用知识图谱优化了其搜索服务以来&#xff0c;知识图谱得到了迅速发展。…