Python中15个递归函数经典案例解析

news2024/9/21 18:32:32

文末赠免费精品编程资料~~

递归是Python编程中一个强大的工具,它允许函数调用自身以解决复杂问题。在本文中,我们将探索15个递归函数的经典案例,从基础到进阶,帮助你理解和掌握递归编程。

1. 阶乘计算

阶乘是一个常见的递归应用,定义为n! = n * (n-1) * … * 1。

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

print(factorial(5))  # 输出: 120

2. 斐波那契数列

斐波那契数列的每一项都是前两项的和。

def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(10))  # 输出: 55

3. 汉诺塔问题

汉诺塔是一个经典的递归问题,涉及将多个盘子从一个柱子移动到另一个柱子。

def hanoi(n, source, target, auxiliary):
    if n > 0:
        hanoi(n - 1, source, auxiliary, target)
        print(f"Move disk {n} from {source} to {target}")
        hanoi(n - 1, auxiliary, target, source)

hanoi(3, 'A', 'C', 'B')

4. 幂运算

计算a的n次方。

def power(a, n):
    if n == 0:
        return 1
    elif n % 2 == 0:
        return power(a * a, n // 2)
    else:
        return a * power(a, n - 1)

print(power(2, 10))  # 输出: 1024

5. 数组求和

递归地计算数组元素的总和。

def array_sum(arr):
    if not arr:
        return 0
    else:
        return arr[0] + array_sum(arr[1:])

print(array_sum([1, 2, 3, 4]))  # 输出: 10

6. 字符串反转

使用递归来反转字符串。

def reverse_string(s):
    if len(s) <= 1:
        return s
    else:
        return reverse_string(s[1:]) + s[0]

print(reverse_string("hello"))  # 输出: "olleh"

7. 找出数组中的最大值

递归地找出数组中的最大值。

def find_max(arr):
    if len(arr) == 1:
        return arr[0]
    else:
        sub_max = find_max(arr[1:])
        return arr[0] if arr[0] > sub_max else sub_max

print(find_max([3, 1, 4, 1, 5, 9]))  # 输出: 9

8. 二叉树遍历

递归地遍历二叉树。

class Node:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def inorder_traversal(node):
    if node is not None:
        inorder_traversal(node.left)
        print(node.val, end=" ")
        inorder_traversal(node.right)

root = Node(1, Node(2), Node(3))
inorder_traversal(root)  # 输出: 2 1 3

9. 平衡括号检查

检查字符串中的括号是否平衡。

def balanced_parentheses(s):
    if not s:
        return True
    if s[0] == '(' and s[-1] == ')':
        return balanced_parentheses(s[1:-1])
    else:
        return False

print(balanced_parentheses("(())"))  # 输出: True

10. 帕斯卡三角形

生成帕斯卡三角形。

def pascals_triangle(n):
    if n == 1:
        return [1]
    else:
        row = [1]
        prev_row = pascals_triangle(n - 1)
        for i in range(len(prev_row) - 1):
            row.append(prev_row[i] + prev_row[i + 1])
        row.append(1)
        return row

for i in range(1, 6):
    print(pascals_triangle(i))

11. 迷宫路径

寻找迷宫的解决方案。

def maze_path(x, y, m, n):
    if x == m or y == n:
        return []
    elif x == m - 1 and y == n - 1:
        return [(x, y)]
    else:
        paths1 = maze_path(x + 1, y, m, n)
        paths2 = maze_path(x, y + 1, m, n)
        for path in paths1 + paths2:
            path.insert(0, (x, y))
        return paths1 + paths2

m, n = 3, 3
paths = maze_path(0, 0, m, n)
for path in paths:
    print(path)

12. 字符串排列

生成字符串的所有可能排列。

def string_permutations(s):
    if len(s) == 1:
        return [s]
    else:
        permutations = []
        for i in range(len(s)):
            char = s[i]
            remaining_chars = s[:i] + s[i+1:]
            for permutation in string_permutations(remaining_chars):
                permutations.append(char + permutation)
        return permutations

print(string_permutations('abc'))

13. 八皇后问题

解决八皇后问题。

def solve_n_queens(n):
    solutions = []
    def place_queen(row, cols):
        if row == n:
            solutions.append(cols)
            return
        for col in range(n):
            if all(abs(c - col) not in (0, row - i) for i, c in enumerate(cols[:row])):
                place_queen(row + 1, cols + [col])
    place_queen(0, [])
    return solutions

for solution in solve_n_queens(8):
    print(solution)

14. 斗地主发牌

模拟斗地主游戏发牌过程。

import random

def deal_cards():
    cards = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2'] * 4 + ['小王', '大王']
    random.shuffle(cards)
    hands = {'player1': [], 'player2': [], 'player3': []}
    for i in range(17):
        for player in hands:
            hands[player].append(cards.pop())
    return hands

print(deal_cards())

15. 字符串匹配

检查一个字符串是否包含另一个字符串。

def string_match(s, pattern):
    if not pattern:
        return True
    if not s:
        return False
    if s[0] == pattern[0]:
        return string_match(s[1:], pattern[1:])
    else:
        return string_match(s[1:], pattern)

print(string_match("hello", "he"))  # 输出: True

高级技巧:

1. 尾递归优化

尾递归是一种特殊的递归形式,其中递归调用是函数执行的最后一个操作。某些语言(如Scheme)会自动优化尾递归,但在Python中,你需要手动转换递归为迭代或使用生成器和协程来避免栈溢出。

2. 记忆化

记忆化是一种优化技术,用于存储先前计算的结果,从而避免重复计算。这对于像斐波那契数列这样的问题特别有用,可以显著提高性能。

def memoize(f):
    cache = {}
    def helper(x):
        if x not in cache:            
            cache[x] = f(x)
        return cache[x]
    return helper

@memoize
def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)

3. 递归与分治法

分治法是一种将问题分解成若干较小的相同或相似子问题的策略,直到这些子问题变得足够简单,可以直接求解。递归是实现分治法的一种自然方式。

实战案例分析:汉诺塔问题

汉诺塔问题是一个典型的递归案例,涉及到将多个圆盘从一个柱子移动到另一个柱子上,但每次只能移动一个圆盘,且大盘不能放在小盘之上。

def hanoi(n, source, target, auxiliary):
    if n > 0:
        # 将n-1个圆盘从source移动到auxiliary
        hanoi(n - 1, source, auxiliary, target)
        # 移动最大的圆盘从source到target
        print(f"Move disk {n} from {source} to {target}")
        # 将n-1个圆盘从auxiliary移动到target
        hanoi(n - 1, auxiliary, target, source)

# 示例调用
hanoi(3, 'A', 'C', 'B')

这个例子展示了如何通过递归解决复杂问题,同时也体现了递归的分治策略。

使用技巧:

  • 在面对问题时,思考是否可以通过分解为子问题来解决,这是递归的一个良好起点。
  • 在设计递归函数时,始终定义清晰的基线情况和递归情况。

递归是编程中一个强大的概念,但使用得当才能发挥其真正的潜力。希望这篇文章能帮助你更好地掌握和应用递归技术!

好了,今天的分享就到这里了,我们下期见。如果本文对你有帮助,请点赞、转发、点个在看吧!

往期推荐

Python处理CSV文件的12个高效技巧

14个一行Python代码创意编程实例

Python极简美学:用一行代码完成的20个日常任务

文末福利

请关注下方公众号并后台回复编程资料免费获取Python编程、人工智能、爬虫等100+本精品电子书。

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

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

相关文章

CSP-CCF 202109-1 数组推导

一、问题描述 二、解答 初版&#xff1a; 只得了60分 #include<iostream> using namespace std; int main() {int n;cin >> n;int B[101] { 0 };int sum_max 0;int sum_min0;//以防错误“使用未初始化的局部变量”&#xff0c;建议所有变量都要初始化&#xf…

2024 Google 开发者大会,沉浸式体验AI社会公益

文章目录 一、现场打卡二、AI 社会公益三、Gemma 模型四、Gemini 模型五、Google Cloud六、现场体验七、带着问题逛展八、学习资源和活动九、结束 Happy Hour 一、现场打卡 大家好&#xff0c;我是小雨。 2024 Google 开发者大会&#xff0c;沉浸式体验AI社会公益 今天我们参加…

ERD Online即将突破 4500 用户的喜悦与展望

亲爱的朋友们&#xff1a; 大家好&#xff01; 今天&#xff0c;我怀着无比激动的心情&#xff0c;要与大家分享一个令人振奋的消息&#xff1a;我们的网站用户即将突破 4500 大关&#xff01; 这一路走来&#xff0c;充满了挑战与艰辛&#xff0c;但每一次的困难都成为了我们前…

2024新型数字政府综合解决方案(十)

新型数字政府综合解决方案融合先进的人工智能、大数据、区块链及云计算技术&#xff0c;旨在通过数据共享、智能分析与自动化处理&#xff0c;打造高效、透明、安全的政务环境&#xff0c;优化服务流程&#xff0c;提升决策科学性&#xff0c;加强信息安全&#xff0c;实现政府…

java入门-成员内部类和静态内部类的访问

&#xff08;一&#xff09;成员内部类 package InnerClass;import javax.print.attribute.standard.MediaSize;public class Outer {//2外部类中的成员private int age99;public static String a;public class Inner{//普通的成员内部类//1.1成员变量public String name;priva…

删除镜像报子镜像依赖错误

1、删除镜像报子镜像依赖错误 出现这个错误的原因是因为有其他镜像依赖需要删除的镜像。 2解决方法 2.1首先查看无法删除的镜像被哪些镜像所依赖 docker image inspect --format{{.RepoTags}} {{.Id}} {{.Parent}} $(docker image ls -q --filter since${image_id}) # ${ima…

数据结构:线性结构之顺序表、链表篇

数据结构&#xff1a;顺序表、链表篇 线性表一、顺序表&#xff08;一&#xff09;顺序表的结构定义&#xff08;二&#xff09;顺序表的功能实现1、初始化2、销毁3、扩容4、插入5、删除 &#xff08;三&#xff09;顺序表例题分析1、删除有序数组中的重复项2、合并两个有序数组…

【Hot100】LeetCode—73. 矩阵置零

目录 1- 思路开辟额外两个一维数组 2- 实现⭐53. 最大子数组和——题解思路 3- ACM 实现 原题连接&#xff1a;73. 矩阵置零 1- 思路 开辟额外两个一维数组 1- 利用额外的两个一维数组 boolean 数组空间&#xff0c;遇到 0 则将当前位置的元素设置为 true 一维 row 数组&…

如何判断一个dll/exe是32位还是64位

通过记事本判断&#xff08;可判断C或者C#&#xff09; 64位、将dll用记事本打开&#xff0c;可以看到一堆乱码&#xff0c;但是找到乱码行的第一个PE&#xff0c;如果后面是d?则为64位 32位、将dll用记事本打开&#xff0c;可以看到一堆乱码&#xff0c;但是找到乱码行的第…

最好用的Linux发行版---WSL

使用debian开发半年&#xff0c;那个号称稳定的操作系统&#xff0c;ubuntu也是基于它的testing版本开发的&#xff0c;在一次设置testing更新后英伟达驱动掉了、引导区无法启动、bios损坏&#xff0c;现在老实了&#xff0c;换回了Window&#xff0c;并且激进的选择了win11&am…

c语言中的宏函数及c++的内联函数及auto及NULL

c的内联函数 使用内联函数可以减少函数栈帧的开销。 Swap(a, b); 00A516C8 mov eax,dword ptr [a] 00A516CB mov dword ptr [ebp-20h],eax 00A516CE mov ecx,dword ptr [b] 00A516D1 mov dword ptr [a],ecx 00A516D4 mov …

Linux登录后自动健康检查:一键掌握系统状态

Linux登录后自动健康检查&#xff1a;一键掌握系统状态 最近开始公众号文章也开始同步更新了&#xff0c;对Java、大数据、人工智能、开发运维相关技术分享&#xff0c;文章对您有用的话&#xff0c;辛苦您也关注下公众号&#xff0c;感谢&#xff01; 引言 当我们登录到某些服…

rt-thread 打开flashdb若干问题

1、打开FAL和SFUD功能 2、打开FLASHDB时&#xff0c;想用utest测试工程&#xff0c;结果报错&#xff0c;缺少mkdir函数&#xff1a; 解决办法&#xff1a;打开DFS RT-Thread Components → DFS: device virtual file system 重新编译

大数据-87 Spark 集群 案例学习 Spark Scala 案例 手写计算圆周率、计算共同好友

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

windows重装系统后无法安装软件,Windows软件无法打开,缺少dll,缺少c++运行库

如果你使用Directx&#xff0c;要么识别不出来&#xff0c;要么装上之后更新会发现重复安装了很多运行库 装一个visual stiudio&#xff1a;<Visual Studio 2022 IDE - 适用于软件开发人员的编程工具> 选择使用C游戏开发、.Net桌面开发 然后安装即可

学习Java的日子 Day71 手写一个SpringMVC的框架(一)

手写一个SpringMVC的框架 1.理解为什么要写这样一个框架 SpringMVC 实际上跟Servlet是一样&#xff0c;都是 Controller的一个解决方案&#xff0c;也就是说我们手写这个框架的目的就是为了替换原来的 Servlet 注意&#xff1a; spring不是框架&#xff0c;springMVC才是框架&…

一文入门mysql 数据库

一、数据库概述 什么是数据库 数据库是一个用于存储和管理数据的仓库。数据按照特定的格式存储&#xff0c;可以对数据库中的数据进行增加、修改、删除和查询操作。数据库的本质是一个文件系统&#xff0c;按照一定的逻辑结构组织数据&#xff0c;以方便高效地访问和维护。 什…

使用Python创建LNK文件选择器并导出配置文件

在这篇博客中&#xff0c;我将介绍如何使用Python的wxPython库开发一个GUI应用程序&#xff0c;该应用程序可以选择文件夹中的.lnk&#xff08;快捷方式&#xff09;文件&#xff0c;并将选中的文件导出为特定格式的buttons.ini配置文件。这个工具非常适合用来快速生成配置文件…

使用Java调用Apache commons-text求解字符串相似性实战

目录 前言 一、字符串距离的几种计算方法 1、Levenshtein 距离 2、Overlap Coefficient计算 3、Q-gram Matching 4、余弦相似性计算 二、基于余弦相似性的基地名称对比 1、加载百科中的基地信息列表 2、设置忽略词列表 3、将数据库地名和Excel进行对比 三、总结 前言…

c语言音频.wav读写示例

1 .wav格式说明 一. RIFF 概念 在 Windows 环境下&#xff0c;大部分的多媒体文件都依循着一种结构来存放信息&#xff0c;这种结构称为"资源互换文件格式"(Resources lnterchange File Format)&#xff0c;简称 RIFF。例如声音的 WAV 文件、视频的 AV1 文件等等均…