递归视角下

2023-09-19 12:04:37
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

第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

第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 多平台发布

更多推荐

数据库JDBC编程

JDBCJDBC是干啥的呢?简单来说就是用java代码操作数据库各种数据库,在开发的时候,就会提供一组编程接口(API)API:ApplicationProgramInterface简单来说就是有个软件,这个软件给你一些功能,你基于这些功能能对这个软件干啥API往往是以函数,类的形式来提供的,说白了就是这个API在这个

130. 被围绕的区域

130.被围绕的区域题目-中等难度示例1.新建board+bfs2.哈希+bfs题目-中等难度给你一个mxn的矩阵board,由若干字符‘X’和‘O’,找到所有被‘X’围绕的区域,并将这些区域里所有的‘O’用‘X’填充。示例示例1:输入:board=[[“X”,“X”,“X”,“X”],[“X”,“O”,“O”,“X”

WinApp自动化测试之工具的选择

WinApp(WindowsAPP)是运行在Windows操作系统上的应用程序,通常会提供一个可视的界面,用于和用户交互。例如运行在Windows系统上的MicrosoftOffice、PyCharm、VisualStudioCode、Chrome,都属于WinApp。常见的WinApp,其扩展名基本都是*.exe,运

电动车充电桩存在网络安全风险吗?

近年来,随着纯电和混动汽车数量的爆炸式增长,其配套的充电桩的需求也呈直线攀升趋势。不过,这些充电桩可能面临着独特的网络安全风险。只要黑客们掌握了足够的相关信息,他们不但能够远程关闭供电网络,甚至会入侵和篡改汽车的设置。下面,我们将深入讨论此类至关重要的安全问题。为什么电动汽车充电桩会存在网络安全风险?2021年,美国曾

数据分析及治理工程师

背景企业的信息化建设需要数据,那么数据是很重要的,数据分析的目的在于为业务服务,而为了更好的达成这一目的。对于元数据的采集和主数据的分析,以及数据标准的制定,和数据质量的保证是非常重要的。主数据管理面临的问题分析主数据治理可以提高数据的特征一致性,识别唯一性,高度共享性,长期有效性,可以获得一个单一的基础数据来源,为企

互联网摸鱼日报(2023-09-22)

互联网摸鱼日报(2023-09-22)36氪新闻通过AI打造车联网地图,「Mapbox」获软银2.8亿美元E轮投资消失的维密门店,以及背后的内衣暗战白酒品牌频跨界:饮料就酒,越喝越有张一鸣北美电商大冒险拆解小程序短剧“一天进账1200万”商业真相​奈飞继续“飞翔”A股银行回购为何“按兵不动”?监管机制约束,部分银行资本

热更新的前置模块:AB管理器

引言本系列是《8年主程手把手打造Cocos独立游戏开发框架》,欢迎大家关注分享收藏订阅。前面的文章给大家介绍了手敲Cocos独立游戏开发框架中常用到的UI管理器和资源管理器,为了减少包体的大小,我们需要引入热更新的模块,但是热更新的前提是把资源打成AssetBundle(简称AB),本文笔者给大家介绍一下AB和AB管理

【MySQL】SQL优化

SQL优化插入数据普通插入:采用批量插入(一次插入的数据不建议超过1000条,500-1000为宜)手动提交事务主键顺序插入(主键顺序插入的效率大于乱序插入)大批量插入:如果一次性需要插入大批量数据,使用insert语句插入性能较低,此时可以使用MySQL数据库提供的load指令插入。#客户端连接服务端时,加上参数--

【Leetcode Sheet】Weekly Practice 7

LeetcodeTest1462课程表Ⅳ(9.12)你总共需要上numCourses门课,课程编号依次为0到numCourses-1。你会得到一个数组prerequisite,其中prerequisites[i]=[ai,bi]表示如果你想选bi课程,你必须先选ai课程。有的课会有直接的先修课程,比如如果想上课程1,你

Zookeeper集群 + Kafka集群

Zookeeper集群+Kafka集群Zookeeper概述Zookeeper定义*Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的Apache项目。Zookeeper工作机制*****Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数

PY32F003F18之ADC问题

普然单片机PY32F003F18的内部有一个LDO,其电压固定为1.2V。我在用官方程序测试时,若接上USB转串口的RX导线,向PC发送数据,读内部参考电压比较正确,但是,当接上USB转串口的TX导线时,发现读到内部电压变成了3.3V。见下图:断开USB转串口的TX导线,数据又恢复正常了。用万用表测试该导线电压,为5V

热文推荐