递归视角下 矫情吗;* 2024-03-02 03:51 31阅读 0赞 def listSum(numbers): if not numbers: return 0 else: (f, rest) = numbers return f + listSum(rest) myList = (1, (2, (3, (4,None)))) total = listSum(myList) print(total) while循环何时退出? 恐怕是while循环技巧所在,即选择恰当的变量作为退出循环的条件判断。 下面的栗子选择了哪个变量作为退出条件? 原题来自宁波第23届中小学信息比赛小学组决赛最后一道题。尝试用python代替原题要求的pascal count.pas/exe) ![alt][] 问题描述: 小Q的编程技术在一次搭积木比赛中也成了秘密武器。原来,比赛的规则是这样的:给你N个小木块(全部为一样大小的正方体)。快速搭成如下图规则的形状(下图为5层的规模),要求层数为最大限度。 由于小Q编了个程序,只要输入小木块的个数N,就可以马上求出最多可以搭几层,还剩几个,所以小Q每次都是一次成功,从不需要翻工,速度也就领先了,你会编小Q这样的程序吗? 【输入数据】 输入文件count.in:文件中只有一个整数N,表示小木块的个数,已知1≤N≤2^31。 【输出数据】 输出文件count.out:文件中有两行整数,第一行是最多可以堆的层数,第二行是剩余的小木块 Python语言的搭积木的诀窍 解法仅供参考 图片 递归的妙处: 第一条:每次递归都能将问题规模缩减下来。 第二条:对应递归终止条件,递归必须有个出口,不然会陷入无限递归当中。 第三条:将递归问题细分为更小的递归问题,然后再进行递归调用。 首先,只需要找到相邻两层之间数量关系,较大层数和小木块数量之间的关系表达为为consumer()函数 请看图:第1层是1,第2层是3,第3层用掉的木块是x,那么前3层用掉的木块总数是前2层用掉的总数,再加上第3层的木块数量。 留意:前3层和第3层所指不同,显然前3层包含第3层。持续倒推,就可以建立起第n层和第1层之间的数量关系。 ![alt][alt 1] 第n-1层需要多少个小木块作为输入参数, x = consumer(n-1) 推出第n层需要多少小木块, consumer(n)=consumer(n-1) + 0.5*(n**2+n) 为啥是第2层开始,总能表达为 consumer(n-1) + 0.5*(n**2+n) 为何1-> n 层的cube总的数量 = 第 n-1 层数量 + 0.5\*(n\*\*2+n) 符合以上数学关系的理由是第 n 层木块数量与 n 存在关系,不妨从求解三角形的面积公式得到灵感: 1+2+3+....n = 0.5\*(n\*\*2+n) ![alt][alt 2] 第n层的平面图计算高斯数 please enter the cube numeber:20 4, 0 please enter the cube numeber:100 7, 16.0 please enter the cube numeber:1000 17, 31.0 但python递归的问题爆栈在随手将 n 大到离谱时如约而至!呵呵 please enter the cube numeber:10000000000000 ... RecursionError: maximum recursion depth exceeded in comparison 那么,这时候有两个办法: 1、设法取消递归栈的上限:996 次; 2、或者改用循环的递推实现; 如何理解递归和循环? SOLID原则: 分离出子函数layerSum(n)计算第 n 层有多少cube; 主函数 consumeWhile(total)判断累积cube超过total为退出循环的条件判断; \*可以与递归写法的结果比较是否一致 # SOLID分离原则 def layersSum(n): # 第 n 层有多少cube return 0.5 *(n**2 + n) 上述可以灵活修改每一层的几何形状,如改为正方形等等; def consumeWhile(total): # 表达相邻两层之间的数量关系 # cur,upper = layers(1),layers(2) # upper变量是从 1-n 层共有多少cube cur,layer = 0,0 while cur <= total: cur += layersSum(layer) if cur == total: return layer,0 elif cur > total: return layer-1,total - (cur-layersSum(layer)) layer += 1 total = 100000000 print(consumeWhile(total)) (842, 153956.0) 递归的写法优雅而有趣,但实际项目工程中并不是首选。正如在while循环中看到当 total 数字很大时,递归的不仅运算花费的时间多且易溢出而报错。 这时循环的写法系统的开销更少。 本文由[ mdnice ][mdnice]多平台发布 [alt]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/02/c426c9c710d945b99594df26c1ace2fa.png [alt 1]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/02/6e5ea843803f4dc0ae01a7409c3c6698.png [alt 2]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/02/7336f37aa0cf42a68cd7960d255a9517.png [mdnice]: https://mdnice.com/?platform=4
相关 递归---从台阶问题学习递归、递归优化和非递归 > 递归就是将大问题划分为若干个子问题,各个问题是嵌套关系,最小的那个问题的结果是已知的,大问题不断分解直到达到最小问题的过程叫做“递”,小问题的解释已知的,然后根据这个解回过 电玩女神/ 2023年06月17日 06:57/ 0 赞/ 20 阅读
相关 递归 递归算法基本思想:找出递归子结构性质(原问题的解包含了子问题的解)、用子问题的解来递归定义原问题的解、找出递归终止条件。 示例: 例1 阶乘函数 阶乘函数可 ╰半橙微兮°/ 2022年06月09日 09:14/ 0 赞/ 298 阅读
相关 递归——线性递归与二分递归 递归 线性递归 例子1:数组求和 int sum( int A[], int n) { //数组求和算法:线性递归版 if 向右看齐/ 2022年05月21日 04:41/ 0 赞/ 342 阅读
相关 递归 递归优点:代码简单 代码量少 递归缺点:不易理解 用递归解决问题时,主要思路: 1.将一个大问题分解成子问题 2.子问题除了问题规模会变小,和原问题解决的思路是一 向右看齐/ 2022年05月03日 10:28/ 0 赞/ 224 阅读
相关 递归 1. public class HelloWorld \{ 2. public static void main(String\[\] args)\{ 3. // Sca 女爷i/ 2022年04月12日 10:50/ 0 赞/ 339 阅读
相关 递归 递归Recursion 递归要求 1. 递归一定要有退出条件,递归调用一定要执行到这个退出条件。没有退出条件的递归调用,就是无限调用 2 雨点打透心脏的1/2处/ 2022年02月19日 05:39/ 0 赞/ 312 阅读
相关 递归 问题描述 任何一个正整数都可以用2进制表示,例如:137的2进制表示为10001001。 将这种2进制表示写成2的次幂的和的形式,令次幂高的排在前面,可得到如下表达式:13 冷不防/ 2021年12月24日 08:43/ 0 赞/ 318 阅读
相关 递归 递归 递归就是一个函数直接或间接的调用自己.一般来说,递归需要有边界条件,递归前进段和递归返回段.当边界条件不满足的时,递归前进,当边界条件满足的时候,递归返回. 递归就 ﹏ヽ暗。殇╰゛Y/ 2021年12月12日 06:53/ 0 赞/ 246 阅读
相关 递归 递归只是让你解决方案更加清晰,并没有性能上的优势。实际上,在有些情况下,使用循环的性能更好。正如,在Stack Overflow 上,Leigh Caldwell 说了一句话: 男娘i/ 2021年09月13日 23:58/ 0 赞/ 373 阅读
还没有评论,来说两句吧...