python coding with ChatGPT 专题2| 全解递归算法

文章目录

  • 递归与栈的关系
  • 如何思考递归
    • 汉诺塔
  • 经典题目
    • 入门:斐波那契数列
    • 分治法:归并排序
    • 树的递归遍历
    • 组合问题:子集
    • 搜索问题:N皇后
  • 拓展
    • 阶乘的迭代法
    • 斐波那契数列迭代法
    • 青蛙跳
  • 参考文献

掌握递归是解决许多编程问题的关键,尤其是那些涉及树形结构、组合问题、搜索问题等领域的题目。递归方法的核心在于将问题分解成更小的子问题,直到达到一个基本情况(base case),然后再逐层返回解决整个问题。理解和掌握递归,最好的方式是通过实践一系列逐渐增加难度的问题。

递归与栈的关系

递归的过程就是出入栈的过程

我们以阶乘为例:

def Factorial(n):if n == 0:return 1return factorial(n-1) * n

取 n=3,则过程如下:
在这里插入图片描述 第 1~4 步,都是入栈过程,Factorial(3)调用了Factorial(2),Factorial(2)又接着调用Factorial(1),直到Factorial(0);
第 5 步,因 0 是递归结束条件,故不再入栈,此时栈高度为 4,即为我们平时所说的递归深度;
第 6~9 步,Factorial(0)做完,出栈,而Factorial(0)做完意味着Factorial(1)也做完,同样进行出栈,重复下去,直到所有的都出栈完毕,递归结束。
在这里插入图片描述

每一个递归程序都可以把它改写为非递归版本。我们只需利用栈,通过入栈和出栈两个操作就可以模拟递归的过程,二叉树的遍历无疑是这方面的代表。

如何思考递归

我们怎么判断这个递归计算是否是正确的呢?Paul Graham 提到一种方法,如下:

如果下面这两点是成立的,我们就知道这个递归对于所有的 n 都是正确的。· 当 n=0,1 时,结果正确;
· 假设递归对于 n 是正确的,同时对于 n+1 也正确。

这种方法很像数学归纳法,也是递归正确的思考方式,上述的第 1 点称为基本情况,第 2 点称为通用情况。

在递归中,我们通常把第 1 点称为终止条件,因为这样更容易理解,其作用就是终止递归,防止递归无限地运行下去。

下面我们用1个例子来具体说明这种数学归纳法:

汉诺塔

在这里插入图片描述问题描述为:有三根杆子 A,B,C。A 杆上有 N 个穿孔圆盘,盘的尺寸由上到下依次变大,B,C 杆为空。要求按下列规则将所有圆盘移至 C 杆:

  • 每次只能移动一个圆盘;
  • 大盘不能叠在小盘上面。

问:如何移?最少要移动多少次?

首先看下基本情况,即终止条件:N=1 时,直接从 A 移到 C。

再来看下通用情况:当有 N 个圆盘在 A 上,我们已经找到办法将其移到 C 杠上了,我们怎么移动 N+1 个圆盘到 C 杠上呢?很简单,我们首先用将 N 个圆盘移动到 C 上的方法将 N 个圆盘都移动到 B 上,然后再把第 N+1 个圆盘(最后一个)移动到 C 上,再用同样的方法将在 B 杠上的 N 个圆盘移动到 C 上,问题解决。

def Hanoi(n, a='A', b='B', c='C'):steps = 0if n == 0:return stepsif n==1:steps += 1print(a, '-->', c)return stepssteps += Hanoi(n-1,a,c,b)steps += Hanoi(1,a,b,c)steps += Hanoi(n-1,b,a,c)return steps

在这里插入图片描述

经典题目

在这里插入图片描述

入门:斐波那契数列

斐波那契数列是通过如下递归式定义的:

  • F(0) = 0, F(1) = 1
  • 对于 n > 1,F(n) = F(n-1) + F(n-2)

这意味着,斐波那契数列从0和1开始,之后的每个数字都是前两个数字的和。例如,斐波那契数列的前几个数字是:0, 1, 1, 2, 3, 5, 8, 13, 21…

def fib(n):if n<2:return nreturn  fib(n-1) + fib(n-2)

在这里插入图片描述

分治法:归并排序

归并排序是一种高效的排序算法,基于分治法的一个典型应用。它将一个数组分成两半,对每部分递归地应用归并排序,然后将两个排序好的部分合并成一个最终的排序数组。

步骤:

  1. 分解:将当前区间一分为二,递归地对这两个子区间进行归并排序。
  2. 合并:将两个排序好的子区间合并成一个最终的排序区间。

实现提示
归并过程需要额外的空间来合并两个有序数组,这是归并排序空间复杂度为O(n)的原因。
实现归并排序时,考虑如何优雅地合并两个有序的子数组。
双指针法

def merge_sort(arr):length = len(arr)if length <2:return arrmid = length//2left_half = arr[:mid]right_half = arr[mid:]left_sort = merge_sort(left_half)right_sort = merge_sort(right_half)i = j = k = 0while i < len(left_sort) and j < len(right_sort):if left_sort[i] <= right_sort[j]:arr[k] = left_sort[i]i += 1k += 1else:arr[k] = right_sort[j]j += 1k += 1if i < len(left_sort):arr[k:] = left_sort[i:]if j < len(right_sort):arr[k:] = right_sort[j:]return arr

在这里插入图片描述

树的递归遍历

关于二叉树的深度优先所有(DFS)问题,我们在前面的文章中有详细的讲解。

前序遍历(Preorder Traversal):首先访问根节点,然后递归地做前序遍历左子树,接着递归地做前序遍历右子树。
中序遍历(Inorder Traversal):首先递归地做中序遍历左子树,然后访问根节点,最后递归地做中序遍历右子树。
后序遍历(Postorder Traversal):首先递归地做后序遍历左子树,然后递归地做后序遍历右子树,最后访问根节点。

在Python中,二叉树节点可以通过下面的TreeNode类来表示:

class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = right
def preorderTraversal(root):res = []if not root:return resres.append(root)res.extend(preorderTraversal(root.left))res.extend(preorderTraversal(root.right))return resdef inorderTraversal(root):res = []if not root:return resres.extend(inorderTraversal(root.left))res.append(root)res.extend(inorderTraversal(root.right))return resdef postorderTraversal(root):res = []if not root:return resres.extend(postorderTraversal(root.left))res.extend(postorderTraversal(root.right))res.append(root)return res

组合问题:子集

给定一组不同的整数,返回所有可能的子集(幂集)。解集不能包含重复的子集。

例子

输入:
nums = [1,2,3]

输出:

[  [3],[1],[2],[1,2,3],[1,3],[2,3],[1,2],[]
]

这个问题可以通过递归(回溯算法)来解决。我们之前的文章也讲到过回溯的理论基础和模板。本题的基本思路是遍历所有元素,对于每个元素,我们可以选择将其包含到当前子集中,或者不包含它。每当我们到达数组的末尾时,我们就找到了一个可能的子集,并将其添加到结果列表中。

def subsets(nums):res = []def backtrack(start, path):res.append(path[:])for i in range(start, len(nums)):path.append(nums[i])backtrack(i+1, path)path.pop()# returnbacktrack(0, [])return res

在这里插入图片描述

搜索问题:N皇后

N皇后问题简介
N皇后问题要求在一个N×N的棋盘上放置N个皇后,使得它们互不攻击。这意味着任何两个皇后都不能处于同一行、同一列或同一对角线上。

解题思路
这个问题可以通过回溯法解决,核心思想是逐行放置皇后,并在每一行中尝试所有列,直到找到一个合法的位置。我们需要一个方法来检查在放置每个新的皇后时,棋盘的状态是否仍然合法。

在这里插入图片描述

def solveNQueens(n):board = [["."] * n for _ in range(n)]res = []def isValid(board, row, col):for i in range(row):# 检查列是否合法if board[i][col] == 'Q':return False# 检查左上对角线if col - i - 1 >= 0 and board[row - i - 1][col - i - 1] == 'Q':return False# 检查右上对角线if col + i + 1 < n and board[row - i - 1][col + i + 1] == 'Q':return Falsereturn Truedef backtrack(board, row):if row == n:res.append(["".join(row) for row in board])returnfor col in range(n):if not isValid(board, row, col):continueboard[row][col] = "Q"backtrack(board, row + 1)board[row][col] = "."backtrack(board, 0)return res

拓展

迭代法可以避免递归,并且在实际应用中,迭代通常比递归有更好的性能,尤其是在防止栈溢出方面。

阶乘的迭代法

def factorial(n):if n == 0:return 1pre = 1for i in range(2, n+1):result = i * prepre = resultreturn result

斐波那契数列迭代法

def fib(n):if n==0:return 0if n==1:return 1pre_n_1 = 1pre_n_2 = 0for i in range(2,n+1):result = pre_n_1 + pre_n_2pre_n_2 = pre_n_1pre_n_1 = resultreturn result

青蛙跳

一只青蛙可以一次跳 1 级台阶或者一次跳 2 级台阶,例如:

跳上第 1 级台阶只有一种跳法:直接跳 1 级即可。 跳上第 2 级台阶有两种跳法:每次跳 1 级,跳两次;或者一次跳 2 级。 问要跳上第 n 级台阶有多少种跳法?

递归法

def jump(n):if n <= 2:return nreturn jump(n - 1) + jump(n - 2)

迭代法

def jump(n):if n <= 2:return npre_n_1 = 2pre_n_2 = 1for i in range(3,n+1):result = pre_n_1 + pre_n_2pre_n_2 = pre_n_1pre_n_1 = resultreturn result

参考文献

一文读懂递归算法
一文看懂什么是递归

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

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

相关文章

isaacgym 渲染黑屏

问题描述&#xff1a; isaacgym安装完IsaacGym_Preview_4_Package.tar.gz之后&#xff0c;运行python joint_monkey.py没有任何内容现实&#xff0c;但是终端还是正常输出信息。 环境是ubuntu22服务器&#xff0c;python3.8&#xff0c;nvidia Driver Version: 515.65.01 CUDA…

【JavaSE】解密 继承和多态(下)

前言 紧接着上篇 解密继承和多态&#xff08;上&#xff09;~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 protected关键字 在同一包下同一类可以访问 代码理解 在同一包下不同类可以访问 代码理解 …

HarmonyOS 应用开发之LifecycleForm接口切换LifecycleApp接口切换 LifecycleApp接口切换

LifecycleForm接口切换 FA模型接口Stage模型接口对应d.ts文件Stage模型对应接口onCreate?(want: Want): formBindingData.FormBindingData;ohos.app.form.FormExtensionAbility.d.tsonAddForm(want: Want): formBindingData.FormBindingData;onCastToNormal?(formId: string…

Octavia Venture 成立,打造数十亿美元规模的 AI 价值体系

​随着 OpenAI 相继发布 ChatGPT、Sora 等 AIGC 大模型后&#xff0c;AI 赛道的发展迎来了一轮又一轮的热潮&#xff0c;这也让极具想象力的 AI 赛道涌入大量资金&#xff0c;比如英伟达股票市值短时间内从 1 万亿美元暴涨至 2 万亿美元&#xff0c;就是最好的佐证。当然&#…

Linux ssh免密登录配置

步骤 在本地机器上生成公钥和私钥对。将本地公钥复制到远程机器的~/.ssh/authorized_keys文件中。 实现1 在服务器上生成SSH密钥对 ssh-keygen -t rsa -f /home/id_rsa1ssh-keygen: 这是一个用于生成、管理和转换 SSH 密钥的 OpenSSH 工具。-t rsa: 用于指定要生成的密钥类…

Python学习:面相对象

面向对象 面向对象技术简介 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。方法:类中定义的函数。类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实…

【AI绘画/作图】风景背景类关键词模板参考

因为ds官网被墙,所以翻了IDE的源码整理了下stablestudio里的官方模板&#xff0c;顺便每个模板生成了一份…不知道怎么写关键词的可以参考 Stunning sunset over a futuristic city, with towering skyscrapers and flying vehicles, golden hour lighting and dramatic cloud…

yolov7代码 | model.named_models

文章目录 前言1. print(model)2. print(model.named_models)2.1 print(name)2.2 print(module)2.3 print(f"{name}:: {module}") 3. hasattr(module, weight) 前言 了解model.named_models&#xff0c;为剪枝做准备。 剪枝有一些层如果你不想剪掉&#xff0c;那就用…

实现恒功率控制丨极海APM32F035高压灌溉水泵参考方案

直流无刷电机用途广泛&#xff0c;具有高效节能、使用寿命长、运行可靠无电火花、结构简单易维护等性能优势&#xff0c;在办公设备、智能家居、消费家电、工业设备、医疗设备等领域已规模化落地。随着智能化技术与成本的持续优化&#xff0c;BLDC应用将进一步提升在各行业的渗…

OpenAI官宣,ChatGPT免登录使用

昨天&#xff0c;就在愚人节当天&#xff0c;OpenAI突然宣布ChatGPT3.5向所有人开放&#xff0c;意思是即使没有注册OpenAI的账号&#xff0c;也能体验ChatGPT&#xff0c;就像浏览器一样&#xff0c;联接即可使用。 消息一出&#xff0c;OpenAI的官网直接被大量的用户挤挂了。…

axios 封装 http 请求详解

前言 Axios 是一个基于 Promise 的 HTTP 库&#xff0c;它的概念及使用方法本文不过多赘述&#xff0c;请参考&#xff1a;axios传送门 本文重点讲述下在项目中是如何利用 axios 封装 http 请求。 一、预设全局变量 在 /const/preset.js 中配置预先设置一些全局变量 window.…

adobe stock会员开通付费付款订阅充值教程/adobe stock免费白嫖一个月

登录adobe stock的官网&#xff0c;点击你想要下载的视频&#xff0c;然后点击免费下载&#xff0c;我们点击免费试用按钮&#xff0c;可以看到非常贵&#xff0c;需要80美金一个月&#xff0c;用fomepay可以免费白嫖一个月 点击获取一张虚拟信用卡&#xff0c;就可以白嫖一个…

配mmdetection

1. 安装conda 链接后面补上 2. 装pytorch&#xff0c;版本别装错了 Start Locally | PyTorch用这里面的命令 nvcc --version看cuda版本&#xff08;实验室服务器是11.0&#xff0c;可以用这个11.8的 &#xff09; 检查torch和cuda版本的命令&#xff1a; import torch # …

C语言:二叉树的构建

目录 一、二叉树的存储 1.1 顺序存储 1.2 链式存储 二、二叉树的顺序结构及实现 2.1堆的概念及结构 2.2堆的构建 2.3堆的插入 2.4堆顶的删除 2.5堆的完整代码 三、二叉树的链式结构及实现 3.1链式二叉树的构建 3.2链式二叉树的遍历 3.2.1前序遍历 …

鸿蒙原OS开发实例:【ArkTS类库单次I/O任务开发】

Promise和async/await提供异步并发能力&#xff0c;适用于单次I/O任务的场景开发&#xff0c;本文以使用异步进行单次文件写入为例来提供指导。 实现单次I/O任务逻辑。 import fs from ohos.file.fs; import common from ohos.app.ability.common;async function write(data:…

深入解析大数据体系中的ETL工作原理及常见组件

** 引言 关联阅读博客文章&#xff1a;探讨在大数据体系中API的通信机制与工作原理 关联阅读博客文章&#xff1a;深入理解HDFS工作原理&#xff1a;大数据存储和容错性机制解析 ** 在当今数字化时代&#xff0c;大数据处理已经成为了企业成功的重要组成部分。而在大数据处…

OpenHarmony实战:小型系统 STM32MP1 芯片移植案例

本文章基于意法半导体 STM32MP157 芯片的小熊派 BearPi-HM Micro 开发板&#xff0c;进行小型带屏开发板的移植&#xff0c;实现了 ace_engine_lite、arkui_ui_lite、aafwk_lite、appexecfwk_lite、HDF 等部件基于 OpenHarmony LiteOS-A 内核的适配。移植架构上采用 Board 与 S…

shopee虾皮怎么分析竞品?这些技巧能帮你提升出单量90%+

“竞品分析”长久以来都是运营所纠结的核心问题&#xff0c;没有分析出对标竞品怎么增长销量&#xff0c;却被其他竞品给町上了&#xff0c;导致自身销量不增反减。这种情况我们是无法直观从自身的店铺及商品本身去找到原因的&#xff0c;本质的问题在竞品身上。我们无法控制有…

基于RDMA的云服务能力实践与探索

01 背景 随着基于大数据大模型构建的数据系统越来越有商业价值&#xff0c;机器学习的玩家也越来越多&#xff0c;数据量越来越大。为解决海量数据在服务器之间的同步效率问题&#xff0c;RDMA(Remote Direct Memory Access) 技术逐渐走进了网络技术人员的视野。RDMA为什么…

鸿鹄工程项目管理系统源码:Spring Boot带来的快速开发与部署体验

随着企业规模的不断扩大和业务的快速发展&#xff0c;传统的工程项目管理方式已经无法满足现代企业的需求。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性&#xff0c;企业需要借助先进的数字化技术进行转型。本文将介绍一款采用Spring CloudSpring BootMybat…