【Python 算法零基础 3.递推】

压抑与痛苦,那些辗转反侧的夜,终会让我们更加强大

                                                                                —— 25.5.16

一、递推的概念

        递推 —— 递推最通俗的理解就是数列,递推和数列的关系就好比 算法 和 数据结构 的关系,数列有点像数据结构中的线性表(可以是顺序表,也可以是链表,一般情况下是顺序表),而递推就是一个循环或者迭代的枚举过程,递推本质上是数学问题。


二、509. 斐波那契数

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

给定 n ,请计算 F(n) 。

示例 1:

输入:n = 2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1

示例 2:

输入:n = 3
输出:2
解释:F(3) = F(2) + F(1) = 1 + 1 = 2

示例 3:

输入:n = 4
输出:3
解释:F(4) = F(3) + F(2) = 2 + 1 = 3

方法一 递归

① 终止条件

当 n == 0 时,直接返回 0(对应斐波那契数列的第 0 项)。

当 n == 1 时,直接返回 1(对应斐波那契数列的第 1 项)。

② 递归计算

当 n > 1 时,当前项的值为前两项之和:fib(n) = fib(n-1) + fib(n-2)

递归调用自身计算 fib(n-1) 和 fib(n-2),并返回它们的和。

    def fib(self, n: int) -> int:if n == 0:return 0elif n == 1:return 1else:return self.fib(n -2) + self.fib(n - 1)

方法二 迭代

① 初始化结果列表

创建列表 res,初始值为 [0, 1],对应斐波那契数列的前两项。

② 循环填充中间项

循环范围i 从 2 到 n-1(不包含 n)。

递推公式:每次将 res[i-1] 和 res[i-2] 的和添加到 res 中。

返回结果:返回 res[n],即列表的第 n 项(索引为 n)。

    def fib(self, n: int) -> int:res = [0, 1]for i in range(2, n + 1):res.append(res[i - 1] + res[i - 2])return res[n]                            

三、1137. 第 N 个泰波那契数

泰波那契序列 Tn 定义如下: 

T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2

给你整数 n,请返回第 n 个泰波那契数 Tn 的值。

示例 1:

输入:n = 4
输出:4
解释:
T_3 = 0 + 1 + 1 = 2
T_4 = 1 + 1 + 2 = 4

示例 2:

输入:n = 25
输出:1389537

方法一 递归

① 终止条件

当 n == 0 时,直接返回 0(对应斐波那契数列的第 0 项)。

当 n == 1 时,直接返回 1(对应斐波那契数列的第 1 项)。

当 n == 2 时,直接返回 1(对应斐波那契数列的第 2 项)。

② 递归计算

当 n > 1 时,当前项的值为前三项之和:fib(n) = fib(n-1) + fib(n-2) + fib(n-3)

递归调用自身计算 fib(n-1) 和 fib(n-2)和fib(n-3),并返回它们的和。

class Solution:def tribonacci(self, n: int) -> int:if n == 0:return 0elif n == 1 or n == 2:return 1else:return self.tribonacci(n - 1) + self.tribonacci(n - 2) + self.tribonacci(n - 3)

方法二 迭代

① 初始化结果列表

创建列表 res,初始值为 [0, 1, 1],对应斐波那契数列的前三项。

② 循环填充中间项

循环范围i 从 3 到 n + 1

递推公式:每次将 res[i-1] 和 res[i-2] 和 res[i-3] 的和添加到 res 中。

返回结果:返回 res[n],即列表的第 n 项(索引为 n)。

class Solution:def tribonacci(self, n: int) -> int:res = [0, 1, 1]for i in range(3, n + 1):res.append(res[i - 3] + res[i - 2] + res[i - 1])return res[n]

四、斐波那契数列变形 爬楼梯问题

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

示例 1:

输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶

示例 2:

输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶

方法一 递归 

思路与算法

① 终止条件

当 n == 1 时,只有 1 种爬法(一步)。当 n == 2 时,有 2 种爬法(一步一步或直接两步)。

② 递归分解

当 n > 2 时,最后一步可能是从 n-1 级跨一步到达,或从 n-2 级跨两步到达。

因此,总爬法数为前两级的爬法数之和:climbStairs(n) = climbStairs(n-1) + climbStairs(n-2)

class Solution:def climbStairs(self, n: int) -> int:if n == 1:return 1elif n == 2:return 2else:return self.climbStairs(n - 1) + self.climbStairs(n - 2)

方法二 迭代

思路与算法

① 初始化结果列表

创建列表 res,初始值为 [1, 1],分别对应 n=0 和 n=1 的爬法数。注意:此处 res[0]=1 是为了后续计算方便,实际题目中 n ≥ 1,因此 res[0] 不会被直接使用。

② 循环填充结果列表

循环范围i 从 2 到 n(包含 n)。

递推公式:对于每个 i,计算 res[i] = res[i-1] + res[i-2],即前两级的爬法数之和。

返回结果:返回 res[n],即第 n 级楼梯的爬法数。

class Solution:def climbStairs(self, n: int) -> int:res = [1, 1]for i in range(2, n + 1):res.append(res[i - 1] + res[i - 2])return res[n]

五、二维递推问题

        像斐波那契数列这种问题,是一个一维数组来解决的,有时候一维数组解决不了的问题我们应该升高一个维度看

        长度为 n(1 ≤ n < 40)的只由“A"、"C"、"M"三种字符组成的字符串,可以只有其中一种或两种字符,但绝对不能有其他字符,且禁止出现 M 相邻的情况,问这样的串有多少种?     

思路与算法

① 边界条件处理

当 n = 0 时,直接返回 0(空字符串)。

② 状态定义

dp[i][0]长度为 i 且最后一个字符是 M 的字符串数目。

dp[i][1]长度为 i 且最后一个字符不是 M(即 A 或 C)的字符串数目。

Ⅰ、初始化

当 i = 1 时:dp[1][0] = 1(字符串为 M)。dp[1][1] = 2(字符串为 A 或 C)。

Ⅱ、状态转移(循环 i 从 2 到 n

计算 dp[i][0](末尾为 M):前一个字符不能是 M(否则相邻),因此只能从 dp[i-1][1] 转移而来。递推式:dp[i][0] = dp[i-1][1]

计算 dp[i][1](末尾为非 M):前一个字符可以是 M 或非 M(即 dp[i-1][0] + dp[i-1][1])。当前字符有 2 种选择(A 或 C),因此总数乘以 2。递推式:dp[i][1] = (dp[i-1][0] + dp[i-1][1]) * 2

Ⅲ、结果计算

最终结果为长度为 n 的所有合法字符串数目,即 dp[n][0] + dp[n][1]

def count_valid_strings(n: int) -> int:if n == 0:return 0# dp[i][0]: 长度为i且最后一个字符是M的字符串数目# dp[i][1]: 长度为i且最后一个字符不是M的字符串数目dp = [[0, 0] for _ in range(n + 1)]dp[1][0] = 1  # Mdp[1][1] = 2  # A, Cfor i in range(2, n + 1):dp[i][0] = dp[i-1][1]  # 前一个字符不能是Mdp[i][1] = (dp[i-1][0] + dp[i-1][1]) * 2  # 前一个字符任意,当前选A/Creturn dp[n][0] + dp[n][1]

六、119. 杨辉三角 II

给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

示例 1:

输入: rowIndex = 3
输出: [1,3,3,1]

示例 2:

输入: rowIndex = 0
输出: [1]

示例 3:

输入: rowIndex = 1
输出: [1,1]

提示:

  • 0 <= rowIndex <= 33

进阶:

你可以优化你的算法到 O(rowIndex) 空间复杂度吗?

思路与算法

① 初始化结果列表

创建空列表 resRows,用于存储杨辉三角的每一行。

② 逐行生成杨辉三角

Ⅰ、外层循环i 从 0 到 rowIndex

对于每一行 i,创建空列表 resCols 用于存储当前行的元素。

Ⅱ、内层循环j 从 0 到 i):

边界条件:当 j 是当前行的第一个或最后一个元素时(即 j == 0 或 j == i),直接添加 1

递推关系:否则,当前元素的值为上一行的 j-1 和 j 位置元素之和(即 resRows[i-1][j-1] + resRows[i-1][j])。将当前行 resCols 添加到 resRows 中。

返回指定行:循环结束后,返回 resRows 中的第 rowIndex 行。

class Solution:def getRow(self, rowIndex: int) -> List[int]:resRows = []for i in range(rowIndex + 1):resCols = []for j in range(i + 1):if j == 0 or j == i:resCols.append(1)# f[i][j] = f[i - 1][j - 1] + f[i - 1][j]else:resCols.append(resRows[i - 1][j] + resRows[i - 1][j - 1])resRows.append(resCols)return resRows[rowIndex]

七、119. 杨辉三角 II 空间优化

给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

示例 1:

输入: rowIndex = 3
输出: [1,3,3,1]

示例 2:

输入: rowIndex = 0
输出: [1]

示例 3:

输入: rowIndex = 1
输出: [1,1]

提示:

  • 0 <= rowIndex <= 33

进阶:

你可以优化你的算法到 O(rowIndex) 空间复杂度吗?

算法与思路

① 初始化二维数组 f

创建一个 2 行、rowIndex+1 列的二维数组 f,用于存储中间结果。初始化 pre = 0 和 now = 1,分别表示当前行和前一行的索引。

② 设置初始条件

f[pre][0] = 1,对应杨辉三角的第一行 [1]

③ 逐行生成杨辉三角

Ⅰ、外层循环i 从 0 到 rowIndex

遍历每一行,生成当前行的元素。

Ⅱ、内层循环j 从 0 到 i

边界条件:当 j 是当前行的第一个或最后一个元素时,设为 1

递推关系:否则,当前元素的值为前一行的 j 和 j-1 位置元素之和(即 f[pre][j] + f[pre][j-1])。更新 pre 和 now 的值,交换当前行和前一行的角色。

返回结果:循环结束后,pre 指向的行即为所求的第 rowIndex 行,返回 f[pre]

class Solution:def getRow(self, rowIndex: int) -> List[int]:f = []for i in range(0, 2):l = []for j in range(rowIndex + 1):l.append(0)f.append(l)pre = 0now = 1f[pre][0] = 1for i in range(0, rowIndex + 1):l = []for j in range(i + 1):if j == 0 or j == i:f[now][j] = 1else:f[now][j] = f[pre][j] + f[pre][j - 1]pre, now = now, prereturn f[pre]

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

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

相关文章

淘宝扭蛋机系统开发前景分析:解锁电商娱乐化新蓝海

在电商行业竞争日益白热化的当下&#xff0c;如何通过创新玩法提升用户粘性、激活消费潜力&#xff0c;成为平台突破增长瓶颈的关键。淘宝扭蛋机系统作为“电商娱乐”的跨界融合产物&#xff0c;正凭借其趣味性、随机性和社交属性&#xff0c;成为撬动年轻消费市场的潜力工具。…

NHANES指标推荐:UHR

文章题目&#xff1a;Elevated log uric acid-to-high-density lipoprotein cholesterol ratio (UHR) as a predictor of increased female infertility risk: insights from the NHANES 2013-2020 DOI&#xff1a;10.1186/s12944-025-02521-w 中文标题&#xff1a;对数尿酸与高…

【c库主要功能】

1 stdio.h 功能&#xff1a;处理文件和标准输入/输出流的各种函数和类型 包含变量&#xff1a; size_t&#xff1a;无符号整形&#xff0c;sizeof关键字的结果FILE&#xff1a;文件流类型&#xff0c;适合存储文件流信息的对象类型 库宏&#xff1a; stderr、stdin、stdout&a…

npm 报错 gyp verb `which` failed Error: not found: python2 解决方案

一、背景 npm 安装依赖报如下错&#xff1a; gyp verb check python checking for Python executable "python2" in the PATH gyp verb which failed Error: not found: python2 一眼看过去都觉得是Python环境问题&#xff0c;其实并不是你python环境问题&#xf…

常见的请求头(Request Header)参数

1. Accept 作用&#xff1a;告知服务器客户端支持的响应数据格式&#xff08;如 JSON、XML、HTML&#xff09;。示例&#xff1a;Accept: application/json&#xff08;优先接收 JSON 格式数据&#xff09;。 2. Content-Type 作用&#xff1a;说明请求体的数据格式&#xff08…

计算机网络:移动通信蜂窝网络指的是什么?

无线基站的蜂窝网络(Cellular Network)是现代移动通信系统的核心架构,其核心思想是通过蜂窝状小区划分和频率复用,实现广域覆盖、高效频谱利用和动态资源管理。以下从设计原理、网络架构、关键技术及实际挑战等方面深入解析蜂窝网络。 一、蜂窝网络的设计原理 1. 蜂窝结构…

【AI论文】对抗性后期训练快速文本到音频生成

摘要&#xff1a;文本到音频系统虽然性能不断提高&#xff0c;但在推理时速度很慢&#xff0c;因此对于许多创意应用来说&#xff0c;它们的延迟是不切实际的。 我们提出了对抗相对对比&#xff08;ARC&#xff09;后训练&#xff0c;这是第一个不基于蒸馏的扩散/流模型的对抗加…

Word文档图片和图表自动添加序号

0 Preface/Foreword Word文档是办公常用的文档&#xff0c;里面经常会插入图片或者表格&#xff0c;当表格和图片数量过多时&#xff0c;如果有些图片需要删除或者添加&#xff0c;那么大概率需要修改大量图片的序号或者引用记录&#xff0c;如果通过手工一个一个修改&#xf…

软件架构设计--期末复习

质量属性 参考视频&#xff1a;【13.5质量属性-架构评估】 在软件架构中&#xff0c;质量属性是衡量系统设计优劣的关键指标&#xff0c;通常分为运行时属性和非运行时属性。以下是一些常见的质量属性&#xff1a; 一、软件架构中的质量属性 运行时属性&#xff1a; 性能&am…

多指标组合策略思路

一种基于多种技术指标和日历因素的综合交易策略&#xff0c;旨在通过复杂的条件判断来预测市场的短期走势&#xff0c;并据此进行买卖操作。 策略概述 该策略的核心思想是通过结合多个技术指标和日历因素来判断市场的短期趋势&#xff0c;并在合适的时机进行买入或卖出操作。 具…

STM32 HAL驱动程序 内部Flash

hal_flash.c #include "hal_flash.h"volatile uint32_t flashWriteOffset SYS_APP_BAK_SAVE_ADDR_BASE; volatile uint32_t flashReadOffset SYS_APP_BAK_SAVE_ADDR_BASE;/* MCU OTA */ /*擦除指定的Flash页*/ void flash_erase_page(uint8_t flashPage , uint32_…

电子电路:什么是电流离散性特征?

关于电荷的量子化,即电荷的最小单位是电子的电荷量e。在宏观电路中,由于电子数量极大,电流看起来是连续的。但在微观层面,比如纳米器件或单电子晶体管中,单个电子的移动就会引起可观测的离散电流。 还要提到散粒噪声,这是电流离散性的表现之一。当电流非常小时,例如在二…

AI agent与lang chain的学习笔记 (1)

文章目录 智能体的4大要素一些上手的例子与思考。创建简单的AI agent.从本地读取文件&#xff0c;然后让AI智能体总结。 也可以自己定义一些工具 来完成一些特定的任务。我们可以使用智能体总结一个视频。用户可以随意问关于视频的问题。 智能体的4大要素 AI 智能体有以下几个…

react+html2canvas+jspdf将页面导出pdf

主要使用html2canvasjspdf 1.将前端页面导出为pdf 2.处理导出后图表的截断问题 export default function AIReport() {const handleExport async () > {try {// 需要导出的内容idconst element document.querySelector(#AI-REPORT-CONTAINER);if (!element) {message.err…

FFmpeg:多媒体处理的终极利器

FFmpeg详细介绍 1. 定义与基本概述 FFmpeg是一套开源的跨平台多媒体处理工具集,最初由法国程序员Fabrice Bellard于2000年开发,其名称源自“Fast Forward MPEG”,体现了其高效处理MPEG格式的能力。它不仅是命令行工具,还包含多个库和开发套件,支持视频转码、剪辑、合并、…

【应用开发十】pwm

1 应用层操作PWM 与LED设备一样&#xff0c;操作PWD也是通过sysfs方式 1&#xff09; 所在目录&#xff1a;/sys/class/pwm&#xff0c;该目录下的文件为pwmchipX&#xff0c;为PWM控器&#xff0c;I.MX6ULL有八个pwm控制器 1.1 pwm 控制器 PWM控制器里内容&#xff08;即pw…

LeetCode算 法 实 战 - - - 双 指 针 与 移 除 元 素、快 慢 指 针 与 删 除 有 序 数 组 中 的 重 复 项

LeetCode算 法 实 战 - - - 双 指 针 与 移 除 元 素、快 慢 指 针 与 删 除 有 序 数 组 中 的 重 复 项 第 一 题 - - - 移 除 元 素方 法 一 - - - 双 重 循 环方 法 二 - - - 双 指 针方 法 三 - - - 相 向 双 指 针&#xff08;面 对 面 移 动&#xff09; 第 二 题 - - -…

设计模式系列(03):设计原则(二):DIP、ISP、LoD

本文为设计模式系列第3篇,聚焦依赖倒置、接口隔离、迪米特法则三大设计原则,系统梳理定义、实际业务场景、优缺点、最佳实践与常见误区,适合系统学习与团队协作。 目录 1. 引言2. 依赖倒置原则(DIP)3. 接口隔离原则(ISP)4. 迪米特法则(LoD)5. 常见误区与反例6. 最佳实…

计算机图形学中MVP变换的理论推导

计算机图形学中MVP变换的理论推导 课程地址&#xff1a;Computing the Pixel Coordinates of a 3D Point 知识铺垫&#xff1a;矩阵的真实内涵 矩阵的每一列/行&#xff08;左乘和右乘的区别&#xff09;代表了新坐标系的基向量在原基向量构成的坐标系中的坐标&#xff0c;这…

先说爱的人为什么先离开

2025年5月19日&#xff0c;15~23℃&#xff0c;贼好的一天&#xff0c;无事发生 待办&#xff1a; 2024年税务申报 《高等数学2》取消考试资格学生名单 《物理[2]》取消考试资格名单 5月24日、25日监考报名 《高等数学2》备课 《物理[2]》备课 职称申报材料 教学技能大赛PPT 遇…