基于python的leetcode算法介绍之递归

news2024/9/29 15:34:38

文章目录

  • 零 算法介绍
  • 一 简单示例 辗转相除法
  • Leetcode例题与思路
    • [509. 斐波那契数](https://leetcode.cn/problems/fibonacci-number/)
      • 解题思路:
      • 题解:
    • [206. 反转链表](https://leetcode.cn/problems/reverse-linked-list/)
      • 解题思路:
      • 题解:
    • [面试题 08.06. 汉诺塔问题](https://leetcode.cn/problems/hanota-lcci/)
      • 解题思路:
      • 题解:
    • [94. 二叉树的中序遍历](https://leetcode.cn/problems/binary-tree-inorder-traversal/)
      • 解题思路:
      • 题解:
    • [101. 对称二叉树](https://leetcode.cn/problems/symmetric-tree/)
      • 解题思路:
      • 题解:

零 算法介绍

递归算法是传统算法中较为简单、基础且实用的一个部分。其核心思想就是通过函数对自身的调用,来实现多层嵌套的过程。而在函数递归的时候,为了保证程序的正常运行,我们需要在程序中设置出口,即需要一个判断条件来终止递归。最简单且常用的递归算法就有通过辗转相除法求两个数的最大公因数问题

一 简单示例 辗转相除法

辗转相除法,也被称为欧几里得算法,是一种求两个整数的最大公因数(GCD)的经典算法。这个算法基于一个原理:两个整数的最大公因数等于较小数和两数相除余数的最大公因数。

具体步骤如下:

  1. 将两个数(假设为a和b)中的大数a除以小数b,得到余数r。

  2. 将b和余数r作为新的两个数,重复步骤1,直到余数为0。

  3. 余数为0时的除数就是最大公因数。

以下是通过循环求解的思路:

# 被除数 将会等于 除数
# 除数 将会等于 余数
# 考虑能否被递归
# 1. 是否存在相同的算法
# 2. 它的终止条件是否唯一
# 考虑到递归的终止条件
# 递归是从最后一层反向传到第一层
def gcd(a, b):  
    while b != 0:  
        a, b = b, a % b  
    return a  

print(gcd(48, 18))
# 18

而当我们采用递归的方式实现时:

def gcd(a, b):
    return gcd(b, a % b) if a % b != 0 else b
  
print(gcd(48, 18))
# 18

Leetcode例题与思路

接下来,我们列举关于Leetcode的五道例题,并通过递归的方式进行求解:

509. 斐波那契数

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

F(0) = 0,F(1) = 1

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

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

解题思路:

关于这道题,其实题目中已经给清了思路,我们按照公式整理即可,详情可看题解。

题解:

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

206. 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

在这里插入图片描述

解题思路:

这道题的解题思路其实有很多,递归仅是其中一个,由于本章是关于递归算法的介绍,所以不做其他方面的阐述。

那么我们来说一下递归的解法:

首先关于递归算法,我们最需要关注的问题是,它的终止条件是什么? 在这道题里,链表的终止条件似乎是循环到head == None才算结束了。但是问题仅是这样吗?我们需要向下思考一层,那就是当我们在最后一个节点的情况下如何指向上一个节点?在单链表中,显然这是不被允许的!所以,这道题有很关键的一步是,我们判断终止的条件是head.next ≠ None

当终止条件考虑过后,我们就可以考虑递归的主体了。在主程序中,由于我们的条件保证head.next ≠ None,所以我们可以使得head.next.next = head 这样就可以保证当前节点的下一个节点指向自己。而为了保证我们最后可以拿到逆序后的头节点,我们只需要返回原来链表中的最后一个元素。

题解:

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if head is None or head.next is None:    # 判断边界并返回逆序后的头节点
            return head
        renode = self.reverseList(head.next)
        head.next.next = head
        head.next = None
        return renode

面试题 08.06. 汉诺塔问题

在经典汉诺塔问题中,有 3 根柱子及 N 个不同大小的穿孔圆盘,盘子可以滑入任意一根柱子。一开始,所有盘子自上而下按升序依次套在第一根柱子上(即每一个盘子只能放在更大的盘子上面)。移动圆盘时受到以下限制:
(1) 每次只能移动一个盘子;
(2) 盘子只能从柱子顶端滑出移到下一根柱子;
(3) 盘子只能叠在比它大的盘子上。

请编写程序,用栈将所有盘子从第一根柱子移到最后一根柱子。

你需要原地修改栈。

解题思路:

汉诺塔是一道非常经典的递归题目,我也非常喜欢。解这道题最好你玩过汉诺塔,这样你就会有一个基本的逻辑在。不说其他的了,我们来说一下汉诺塔的解题思路:关于这道题,我做一个很形象的比喻:把大象关进冰箱需要几步?只需要三步:打开冰箱门,放进大象,关上冰箱门。忽然这么一说你可能摸不到头脑,但我们可以这么理解:

将汉诺塔从原始柱移到目标柱需要几步?只需要三步:把前N-1层移动到临时柱,把第N层移动到目标柱,把前N-1层在移动到目标柱上。

记住这个逻辑,后面代码中,我将通过raw,temp,aim来替换掉A,B,C。

那这道题目的终止条件是什么呢?

当然是仅剩下一层的时候我该怎么移动了。很简单,从原始柱移动到目标柱就可以了。

那么由于对于N层来说,我们需要把前N-1层移动到临时柱。那么对于前N-1层,那个临时柱就变成了它的目标。提示到这里,聪明的你应该有想法了,那么更精彩的就在代码里了。

题解:

class Solution:
    def hanota(self, A: List[int], B: List[int], C: List[int]) -> None:
        n = len(A)
        raw, temp, aim = A, B, C
        self.move(n, raw, temp, aim)

    def move(self, n, raw, temp, aim):
        if n == 1:
            aim.append(raw[-1])
            raw.pop()
            return 
        else:
            self.move(n-1, raw, aim, temp)
            aim.append(raw[-1]) 
            raw.pop() 
            self.move(n-1,temp, raw, aim)

94. 二叉树的中序遍历

给定一个二叉树的根节点 root ,返回 它的 中序 遍历

解题思路:

如果你不知道二叉树的遍历,那么很遗憾,你需要先补习相关知识,之前说的递归的知识其实已经足够了。二叉树和递归其实是相互纠缠的一对儿,所以我们还要讲几到二叉树的题目。

中序遍历:即左子树,根结点,右子树三步走。

而在这道题中,我们先找一下终止条件:即作为树的叶子节点即可返回。

而在程序主体中,我们进需要按照左,中,右的逻辑对列表做拼接即可。

还需要注意一点,就是要小心空树哦。

题解:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if root == None:
            return []
        elif root.left == None and root.right == None:
            return [root.val]
        else:
            my_list = self.inorderTraversal(root.left) if root.left != None else []
            my_list = my_list + [root.val]
            my_list = my_list + self.inorderTraversal(root.right) if root.right != None else my_list
            return my_list

101. 对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

解题思路:

如何判断一个二叉树是否对称?它仅满足一个条件,即二叉树的左子树和右子树呈现镜像对称。什么意思呢?就是左子树的右节点应该风雨右子树的左节点。

去判断一棵树满足对称二叉树的条件,不如去找他不满足的地方。这是算法那种的一个很重要的思想:判断成功需要挨个证明,但判断失败仅需要一次就行

那接下来,我们来说一下终止条件:

  1. 成功:当左右镜像最后都成为None的情况下,就是最终的胜利。

  2. 迭代:当左右都没到叶子节点的时候,且左右根的值相同。

  3. 失败:不满足以上条件就是失败。

所以代码很简单可以写成一下形式:

题解:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        def search(left, right):
            if left == None and right == None:
                return True
            elif left != None and right != None and left.val == right.val:
                return search(left.left, right.right) and search(left.right, right.left)
            else:
                return False
        return search(root.left, root.right) if root != None else True

以上就是关于递归的一些见解,我将不定期的更新该系列,来完善基于python的算法体系。

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

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

相关文章

最新AI创作系统ChatGPT系统源码+DALL-E3文生图+AI绘画+GPT语音对话功能

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作Ch…

计算机网络 网络层下 | IPv6 路由选择协议,P多播,虚拟专用网络VPN,MPLS多协议标签

文章目录 5 IPv65.1 组成5.2 IPv6地址5.3 从IPv4向IPv6过渡5.3.1 双协议栈5.3.2 隧道技术 6 因特网的路由选择协议6.1 内部网关协议RIP6.2 内部网关协议 OSPF基本特点 6.3 外部网关协议 BGP6.3.1 路由选择 6.4 路由器组成6.4.1 基本了解6.4.2 结构 7 IP多播7.1 硬件多播7.2 IP多…

vp与vs联合开发-通过FrameGrabber连接相机

添加控件 1.CogRecordDisplay 控件 用于显示图像 初始化相机对象方法 //启动窗体时 调用初始化相机方法 //封装相机关闭方法 //窗体关闭时 调用相机关闭方法 拍照 设置采图事件 // 保存图像 设置曝光按钮事件 1.可变参数

C# pictureBox显示一张图片,我想先释放这个图片以免占用无法修改,(旋转)改完再显示这张图片

效果 public static bool RotateFlip(MyDel Log, string fileName){try{string tempPath Path.GetTempFileName();using (Bitmap bmp new Bitmap(fileName)){float resolution 600; //x,y必须为这个数 误差小于-1bmp.RotateFlip(RotateFlipType.Rotate90FlipNone);bmp.Save(…

智能优化算法应用:基于冠状病毒群体免疫算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于冠状病毒群体免疫算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于冠状病毒群体免疫算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.冠状病毒群体免疫算法4.…

飞天使-k8s-知识点1-kubernetes架构简述

文章目录 名词功能要点 k8s核心要素CNCF 云原生框架简介k8s组建介绍 名词 CI 持续集成, 自动化构建和测试:通过使用自动化构建工具和自动化测试套件,持续集成可以帮助开发人员自动构建和测试他们的代码。这样可以快速检测到潜在的问题,并及早…

C/C++编程中的算法实现技巧与案例分析

C/C编程语言因其高效、灵活和底层的特性,被广大开发者用于实现各种复杂算法。本文将通过10个具体的算法案例,详细探讨C/C在算法实现中的技巧和应用。 一、冒泡排序(Bubble Sort) 冒泡排序(Bubble Sort)是一…

单片机应用实例:LED显示电脑电子钟

本例介绍一种用LED制作的电脑电子钟(电脑万年历)。其制作完成装潢后的照片如下图: 上图中,年、月、日及时间选用的是1.2寸共阳数码管,星期选用的是2.3寸数码管,温度选用的是0.5寸数码管,也可根据…

人工智能中不可预测的潜在错误可能是灾难性的——数学解释

一、说明 有没有人研究评估AI的错误产生的后果有多么严重,是否存在AI分险评估机制?更高维度上,人工智能的未来是反乌托邦还是乌托邦?这个问题一直是争论的话题,各大阵营都支持。我相信我们无法准确预测这两种结果。这是…

画图之C4架构图idea和vscode环境搭建篇

VS Code 下C4-PlantUML安装 安装VS Code 直接官网下载安装即可,过程略去。 安装PlantUML插件 在VS Code的Extensions窗口中搜索PlantUML,安装PlantUML插件。 配置VS Code代码片段 安装完PlantUML之后,为了提高效率,我们最好安装PlantUML相关的代码片段。 打开VS Cod…

React心理健康测试网站系统源码

帮助需要的人更好地了解自己的心理健康状态和人格特征。本模板提供了一个最小的配置,使得React可以在Vite中启用HMR,并且包含了几个ESLint规则。只需要使用react antd-mobile即可轻松部署完成。 源码下载:https://download.csdn.net/downlo…

操作系统系列:Unix进程系统调用fork,wait,exec

操作系统系列:Unix进程系统调用 fork系统调用fork()运用的小练习 wait系统调用Zombiesexec 系列系统调用 开发者可以查看创建新进程的系统调用,这个模块会讨论与进程相关的Unix系统调用,下一个模块会讨论Win32 APIs相关的进程。 fork系统调用…

智能优化算法应用:基于学生心理学算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于学生心理学算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于学生心理学算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.学生心理学算法4.实验参数设定5.算法…

VS+Qt 打包Python程序

书接上回,调用C调用python,下面来谈谈随exe文件打包。 先说下环境vs2019Qt5.12.11python3.8,这里需要注意如果你要适配Win7的系统,python最好是9以下,以上不兼容,也没时间找方法,找到评论说下 如…

实现个人日志命令行工具(C语言)

〇、前言 中午上课的时候,打开 github 看了一下个人主页,虽然最近很忙,但是这个活动记录有点过于冷清: 于是我就想着写一个日志命令行工具,输入以下命令就能将我的日志立即同步到 github 上: mylog toda…

Jenkins+Docker+Gitee搭建自动化部署平台

目录 服务器准备 Docker安装 yum 包更新到最新 设置yum源 安装docker 启动和开机启动 验证安装是否成功 Jenkins安装 拉取镜像 创建映射目录 运行镜像 运行出错 修正权限 重新运行镜像 新建安全组,放通8080端口 激活Jenkins Jenkins插件 Jenkins全…

el-form与el-upload结合上传带附件的表单数据(前端篇)

1.写在之前 本文前端采用Vue element-plus技术栈,前端项目参考yudao-ui-admin-vue3项目与Geeker-Admin项目。 这篇文章是el-form与el-upload结合上传带附件的表单数据(后端篇)-CSDN博客姐妹篇,后端篇文章主要讲的是后端的实现逻…

限流原理与实践:固定窗口、滑动窗口、漏桶与令牌桶解析

方案一、固定窗口限流算法 这里我们通过一个 demo 来介绍固定窗口限流算法。 创建一个 FixWindowRateLimiterService 类。 Service public class FixWindowRateLimiterService {Resourceprivate StringRedisTemplate stringRedisTemplate;private static final DefaultRedisSc…

新手上路:自动驾驶行业快速上手指南

文章目录 1.自动驾驶技术的发展1.1 工业革命驱动自动驾驶技术发展1.2 想象中的未来:科幻作品中的自动驾驶汽车1.3 自动驾驶技术萌芽与尝试1.4 百花争鸣:自动驾驶科技巨头与创业公司并进 2.个人开发者,如何玩转自动驾驶?2.1 灵活易…

Opencv实验合集——实验六:模板匹配

1.概念 模板匹配旨在在图像中找到与给定模板最相似的部分。其核心思想是通过滑动模板,计算每个位置与模板的相似性,然后找到最匹配的位置。这一过程常涉及选择匹配度量方法,如平方差匹配、归一化平方差匹配、相关性匹配等。模板匹配在目标检…