算法模型从入门到起飞系列——递归(探索自我重复的奇妙之旅)
文章目录
- 前言
- 一、递归本质
- 1.1 递归的要素
- 1.2 递归特点
- 二、递归&迭代
- 2.1 递归&迭代比较
- 2.2 递归&迭代如何实现相同功能
- 2.2.1 递归实现
- 2.2.2 迭代实现
- 2.2.3 性能对比
- 三、优雅的递归理解
- 3.1 阶乘计算分解
- 3.2 [DFS](https://blog.csdn.net/qq_38315952/article/details/146374720?spm=1001.2014.3001.5501)分解
- 四、尾递归优化(Tail Call Optimization, TCO)
- 4.1 尾递归优化概念
- 4.2 尾递归优化演示
- 五、哪些问题更适合递归解决
- 1. 数学问题
- 2. 分治算法
- 3. 树形结构遍历
- 4. 回溯算法
- 5. 动态规划问题
- 6. 解析嵌套结构
- 7. 递归关系明确的问题
- 献给读者


前言
在编程的世界里,递归是一种既神秘又强大的工具。它宛如一个魔法盒子,能够将复杂的问题简化为更小规模的相同问题,直至找到最基础、可以直接解决的情况。无论是优雅地遍历复杂的树形结构,还是巧妙地解开经典的汉诺塔谜题,递归都能以其独特的方式展现其非凡的魅力。
递归的核心在于函数直接或间接地调用自身,这一过程看似简单,实则蕴含着深邃的逻辑和无限的可能性。通过递归,我们可以构建出简洁而富有表现力的代码,使得解决方案看起来自然而直观。然而,正如任何强大的工具一样,递归也有其双刃剑的一面:如果使用不当,可能会导致程序陷入无限循环,或是消耗过多的系统资源,甚至引发栈溢出错误。
本书旨在深入探讨递归的概念、应用及其背后的设计哲学。我们将从最基本的原则出发,逐步揭开递归的神秘面纱,揭示其在算法设计、数据结构处理以及实际软件开发中的广泛应用。无论你是编程新手,渴望理解递归的基础知识;还是经验丰富的开发者,希望进一步掌握递归优化技巧,本书都将为你提供宝贵的见解和实用的指导。
让我们一同踏上这段探索递归奥秘的旅程,在不断的实践中体会其带来的乐趣与挑战,共同解锁编程艺术中这扇独特的门扉。准备好迎接这场自我重复的奇妙之旅了吗?前方等待着你的,是更加深刻的理解和无尽的创造可能。
一、递归本质
递归是一种在编程和数学中使用的方法,它指的是一个函数或过程直接或间接地调用自身。递归通常用于解决可以被分解为更小的相同问题的问题。这种方法非常强大,但需要小心使用,因为它可能导致无限循环或其他错误,如果设计不当的话。
💡贴士:递归核心就是调用自己,自我分解,化繁为简。
1.1 递归的要素
- 基准情况(Base Case):这是递归过程中的终止条件,用来停止递归调用。没有有效的基准情况会导致无限递归,最终可能耗尽系统资源或导致栈溢出错误。
- 递归步骤(Recursive Step):这是将问题规模减小,并朝向基准情况前进的步骤。在这个过程中,函数会调用自己并传入较小规模的问题参数。
1.2 递归特点
-
自我调用
递归的核心特点是函数直接或间接地调用自身。通过这种方式,复杂的问题可以被分解为更小、更易管理的子问题,直到达到一个可以直接解决的基础情况(基准情况)。 -
基准情况(Base Case)
每个递归函数都必须定义至少一个基准情况,作为递归终止的条件。基准情况是递归过程中最简单的情况,不需要进一步递归来解决。缺乏有效的基准情况会导致无限递归,最终可能引发栈溢出错误。 -
递归步骤(Recursive Step)
在递归步骤中,问题被分解为一个或多个较小规模的相同问题,并通过再次调用递归函数来求解这些子问题。递归步骤的设计至关重要,它决定了递归过程能否逐步接近基准情况,从而正确终止。 -
空间复杂度高
每次递归调用都会在调用栈上创建一个新的帧,用于保存局部变量和返回地址等信息。因此,递归可能会消耗大量的内存,特别是在深度递归的情况下,这可能导致栈溢出错误。相比之下,迭代通常需要较少的额外空间。 -
可能存在性能开销
由于函数调用本身有一定的开销,包括参数传递、局部变量初始化以及控制权转移等,递归可能会比等效的迭代实现慢。此外,重复计算相同子问题的情况(如未优化的斐波那契数列计算)也可能导致效率低下。 -
提升代码可读性
对于某些类型的问题,如树遍历、图搜索算法和分治算法,使用递归可以使代码更加简洁明了,易于理解和维护。递归结构能够直观地反映问题的本质,使得解决方案看起来自然而优雅。 -
尾递归优化
一些现代编程语言支持尾递归优化(Tail Call Optimization, TCO),在这种情况下,如果递归调用是函数执行的最后一步且不需保留当前调用的状态,则编译器或解释器可以优化该递归调用以减少栈空间的使用,甚至将其转换为迭代形式,从而提高效率并避免栈溢出风险。
了解这些特点有助于合理选择何时使用递归解决问题,并采取适当措施优化递归函数的表现。无论是为了提升代码的清晰度还是性能,掌握递归的特点都是编程技能中的重要一环。
二、递归&迭代
2.1 递归&迭代比较
| 特性 | 递归 | 迭代 |
|---|---|---|
| 定义 | 函数直接或间接调用自身来解决问题 | 使用循环结构重复执行一段代码,直到满足特定条件 |
| 基准情况 | 必须明确至少一个终止条件(基准情况),以避免无限递归 | 通过循环条件控制终止,无需显式定义基准情况 |
| 代码风格 | 对于某些问题(如树遍历、分治算法)更加直观和简洁 | 通常需要手动管理循环变量和状态,代码可能较冗长但清晰 |
| 空间复杂度 | 每次递归调用都会在栈上创建一个新的帧,可能导致较高的内存消耗 | 空间效率高,因为只需要固定的额外空间来存储循环变量 |
| 性能 | 可能存在函数调用开销,特别是深度递归时可能导致栈溢出错误 | 通常比递归更高效,因为它避免了函数调用的额外开销 |
| 适用场景 | 天然适合处理具有自我相似性质的问题(如树形结构、图搜索等) | 更适合解决可以通过简单的循环来解决的问题 |
| 优化可能性 | 支持尾递归优化(部分语言),可以减少栈空间使用 | 不需要特殊的优化,但在某些情况下可能需要考虑循环不变量的优化 |
| 示例应用 | 阶乘计算、斐波那契数列、汉诺塔、快速排序、归并排序 | 阶乘计算、斐波那契数列、线性搜索、二分查找 |
2.2 递归&迭代如何实现相同功能
为了更清楚地理解递归和迭代如何实现相同的功能,我们可以以计算阶乘为例。阶乘n!定义为从1到n的所有正整数的乘积(0! = 1)。下面是使用递归和迭代两种方法来实现这一功能的例子。
2.2.1 递归实现
public class Factorial {// 递归方法计算阶乘public static int factorialRecursive(int n) {if (n == 0 || n == 1) {return 1;} else {return n * factorialRecursive(n - 1);}}public static void main(String[] args) {// 测试阶乘函数int number = 5; // 你可以更改这个值来测试不同的输入System.out.println(number + "! = " + factorialRecursive(number));}
}

2.2.2 迭代实现
public class Factorial {// 迭代方法计算阶乘public static int factorialIterative(int n) {if (n < 0) {throw new IllegalArgumentException("Number must be non-negative.");}int result = 1;for (int i = 2; i <= n; i++) {result *= i;}return result;}public static void main(String[] args) {// 测试阶乘函数int number = 5; // 你可以更改这个值来测试不同的输入try {System.out.println(number + "! = " + factorialIterative(number));} catch (IllegalArgumentException e) {System.out.println(e.getMessage());}}
}

2.2.3 性能对比


💡贴士:可以看出递归和迭代实现的效果一样,区别在递归会使用多次重复计算,比如计算5的阶乘会计算4的阶乘一直到1的阶乘,然后又从1的阶乘一个一个叠加上去,相当于走了一个来回,增加了很多开销。
三、优雅的递归理解
如果看到这里还没有理解递归的思想或者无法使用递归处理问题,那么接下来不要眨眼睛,见证奇迹的时刻就要到了。
👉👉👉 所有的递归思想都可以转化成n和n-1的状态关系。
三步走思想:
- 参数(和n有关)。
- 临界条件(数学归纳法中临界条件,这个是最远的状态,一般是当n = 1时的状态值)。
- 计算fn的公式。
3.1 阶乘计算分解
递归思想:
阶乘问题是最好理解的,可以直接分解成f(n) = f(n-1) * n 。那么给定方法

3.2 DFS分解

💡贴士:所有的递归问题都可以换成
fn和fn-1…之间的关系,只不过像DFS这种不是计算的具体的值,而是用的处理操作。需要仔细体会一下fn和fn-1之间的关系。
四、尾递归优化(Tail Call Optimization, TCO)
4.1 尾递归优化概念
尾递归优化(Tail Call Optimization, TCO)是一种编译器或解释器优化技术,旨在优化尾递归调用,使其不会增加额外的栈帧。这意味着在某些情况下,尾递归可以被转换为等效的迭代代码,从而避免了栈溢出的风险并提高了性能。
尾递归是指一个函数在其执行的最后一步调用自身,并且这个递归调用是函数返回值的一部分。换句话说,如果递归调用是函数的最后一个操作,那么它就是一个尾递归调用。
在Java中,标准的JVM并不直接支持尾递归优化(Tail Call Optimization, TCO)。这意味着即使你的函数是尾递归的,JVM也不会自动将其优化为迭代形式。然而,你可以通过手动将尾递归转换为迭代来避免栈溢出问题。
4.2 尾递归优化演示
尽管如此,理解如何编写尾递归函数以及如何手动进行优化是非常有用的。下面我们将展示一个尾递归的阶乘函数示例,并讨论如何手动将其转换为迭代形式。
public class Factorial {// 尾递归方法计算阶乘public static long factorialTailRecursive(long n, long accumulator) {if (n == 0) {return accumulator;} else {return factorialTailRecursive(n - 1, n * accumulator);}}public static void main(String[] args) {// 测试阶乘函数long number = 5; // 你可以更改这个值来测试不同的输入System.out.println(number + "! = " + factorialTailRecursive(number, 1));}
}
在这个例子中,factorialTailRecursive 函数使用了一个累积器 accumulator 来存储中间结果。每次递归调用时,它都会更新 n 和 accumulator 的值,直到达到基准情况(n == 0)。
由于Java不支持尾递归优化,我们可以手动将上述尾递归函数转换为等效的迭代形式:
public class Factorial {// 迭代方法计算阶乘public static long factorialIterative(long n) {long result = 1;for (long i = 2; i <= n; i++) {result *= i;}return result;}public static void main(String[] args) {// 测试阶乘函数long number = 5; // 你可以更改这个值来测试不同的输入System.out.println(number + "! = " + factorialIterative(number));}
}
虽然Java本身不支持尾递归优化,但可以通过使用辅助类或数据结构来模拟这种行为。以下是一个示例,展示了如何使用一个简单的栈来模拟尾递归优化:

import java.util.ArrayDeque;
import java.util.Deque;public class Factorial {// 辅助类用于模拟尾递归private static class FactorialTask {long n;long accumulator;FactorialTask(long n, long accumulator) {this.n = n;this.accumulator = accumulator;}}// 模拟尾递归优化的方法public static long factorialSimulatedTCO(long n) {Deque<FactorialTask> stack = new ArrayDeque<>();stack.push(new FactorialTask(n, 1));while (!stack.isEmpty()) {FactorialTask task = stack.pop();if (task.n == 0) {continue;} else if (task.n == 1) {return task.accumulator;} else {stack.push(new FactorialTask(task.n - 1, task.n * task.accumulator));}}return 1; // 基准情况}public static void main(String[] args) {// 测试阶乘函数long number = 5; // 你可以更改这个值来测试不同的输入System.out.println(number + "! = " + factorialSimulatedTCO(number));}
}
💡贴士:
尽管Java不支持尾递归优化,但我们可以通过以下几种方式来处理这个问题:
👉手动转换为迭代:将尾递归函数转换为等效的迭代形式。
👉使用辅助类模拟:利用栈或其他数据结构来模拟尾递归的过程,从而避免栈溢出。
五、哪些问题更适合递归解决
1. 数学问题
阶乘计算:计算一个数的阶乘是一个经典的递归问题。
斐波那契数列:斐波那契数列中的每一项是前两项之和,非常适合用递归来实现。
最大公约数(GCD):欧几里得算法通过递归方式求解两个数的最大公约数。
2. 分治算法
归并排序:将数组分成两半,分别对每一半进行排序,然后合并结果。
快速排序:选择一个基准元素,将数组分为比基准大和比基准小的两部分,分别对这两部分进行排序。
二分查找:在一个有序数组中查找某个值,每次将搜索范围缩小一半。
3. 树形结构遍历
二叉树遍历:包括前序遍历、中序遍历和后序遍历等。
多叉树遍历:对于任意深度的多叉树,递归遍历是一种直观且高效的解决方案。
图的深度优先搜索(DFS):递归地访问每个相邻节点,直到所有节点都被访问过。
4. 回溯算法
八皇后问题:找到所有可以在棋盘上放置八个皇后而不互相攻击的方案。
迷宫问题:从起点开始,尝试每一条可能的路径,直到找到出口或所有路径都已尝试完毕。
组合和排列问题:生成一组元素的所有可能组合或排列。
5. 动态规划问题
虽然动态规划问题通常可以通过迭代来解决,但在某些情况下,递归结合记忆化(Memoization)可以简化问题的解决过程:
背包问题:给定一组物品,每个物品有一个重量和一个价值,在限定总重量的前提下,如何选择物品使得总价值最大。
最长公共子序列(LCS):找到两个序列的最长公共子序列。
6. 解析嵌套结构
解析表达式树:例如,解析算术表达式时,可以将其表示为一棵树,并通过递归方式对其进行求值。
解析JSON/XML数据:这些数据格式通常包含嵌套的对象和数组,递归方法可以方便地处理这种嵌套结构。
7. 递归关系明确的问题
汉诺塔问题:经典的递归问题,涉及将一系列盘子从一个柱子移动到另一个柱子。
字符串操作:例如,反转字符串、检查回文等,这些问题往往可以通过递归方式进行简单而直观的实现。
献给读者
💯 计算机技术的世界浩瀚无垠,充满了无限的可能性和挑战,它不仅是代码与算法的交织,更是梦想与现实的桥梁。无论前方的道路多么崎岖不平,希望你始终能保持那份初心,专注于技术的探索与创新,用每一次的努力和进步书写属于自己的辉煌篇章。
🏰在这个快速发展的数字时代,愿我们都能成为推动科技前行的中坚力量,不忘为何出发,牢记心中那份对技术执着追求的热情。继续前行吧,未来属于那些为之努力奋斗的人们。
亲,码字不易,动动小手,欢迎 点赞 ➕ 收藏,如 🈶 问题请留言(评论),博主看见后一定及时给您答复,💌💌💌
相关文章:
算法模型从入门到起飞系列——递归(探索自我重复的奇妙之旅)
文章目录 前言一、递归本质1.1 递归的要素1.2 递归特点 二、递归&迭代2.1 递归&迭代比较2.2 递归&迭代如何实现相同功能2.2.1 递归实现2.2.2 迭代实现2.2.3 性能对比 三、优雅的递归理解3.1 阶乘计算分解3.2 [DFS](https://blog.csdn.net/qq_38315952/article/deta…...
YOLO+OpenCV强强联手:高精度跌倒检测技术实战解析
目录 关于摔倒检测 摔倒检测核心逻辑 摔倒检测:联合多种逻辑判断 原理详细解释 1. 导入必要的库 2. 定义函数和关键点连接关系 3. 筛选有效关键点并计算边界框 4. 计算人体上下半身中心点和角度 5. 绘制关键点和连接线 6. 绘制角度标注和检测跌倒 7. 返回处理后的图…...
麒麟银河V10服务器RabbitMQ安装
安装步骤 rabbitMQ依赖于erlang的环境,所以需要先安装erlang,erlang跟rabbitMQ是有版本之间的关联关系的,根据对应的版本去安装下载,保证少出问题。 可以通过官网来查看RabbitMQ和erlang之间的版本对应关系 rabbitMQ和erlang之间…...
React Hooks主要解决什么
1、状态逻辑复用困难 在Hooks出现之前,React组件间的状态逻辑复用主要依赖高阶组件(HOC)和 render props。 Hooks 通过允许创建自定义Hook,使得状态逻辑的复用变得简单而直接 缺点 HOC 可能导致 props 命名冲突render props …...
extern和static的作用(有例子)
一、extern extern的作用 声明而非定义 extern告诉编译器某个变量或函数存在于其他地方(通常是另一个源文件),当前只是声明它,而不是定义它(分配内存)。定义只能在一个地方出现,而声明可以多次…...
基于C#的以太网通讯实现:TcpClient异步通讯详解
基于C#的以太网通讯实现:TcpClient异步通讯详解 在现代工业控制和物联网应用中,以太网通讯是一种常见的数据传输方式。本文将介绍如何使用C#实现基于TCP协议的以太网通讯,并通过异步编程提高通讯效率。我们将使用TcpClient类来实现客户端与服…...
【8】分块学习笔记
前言 分块是一种重要的高级数据结构思想,核心为大段维护,局部朴素。 顺带一提,由于个人技术水平,本篇博客的难度并没有标题所述的 8 8 8 级。分块还是很难的。 分块 分块,是“优雅的暴力”。 分块的基本思想是把数据分为若干…...
Deployment声明式更新与应用式更新对比
目录 1. 声明式更新 特点 相关命令 示例 2. 命令式更新 特点 相关命令 示例 3. 声明式更新 vs 命令式更新 4. 声明式更新的优势 5. 命令式更新的适用场景 6. 总结 在 Kubernetes 中,声明式更新和命令式更新是两种不同的资源管理方式。它们分别通过不同的…...
【蓝桥杯】省赛:分糖果(思维/模拟)
思路 数据很小,直接暴力模拟。 有意思的是一个列表如何当成循环队列写?可以arr[(i1)%n]让他右边超出时自动回到开头。 code import os import sysn int(input()) arr list(map(int,input().split()))ans 0 while 1:arr1 arr.copy()for i in range…...
在 Go 语言中生成单元测试报告
在 Go 语言中生成单元测试报告,你可以使用 go test 命令配合一些参数来实现。以下是一些常用的方法和步骤: 基本测试:首先,确保你的项目已经编写了测试文件(通常以 _test.go 结尾)。然后,在项目…...
Metasploit Framework(MSF)使用教程与命令详解
Metasploit Framework(简称MSF)是一款功能强大的开源渗透测试工具,广泛应用于网络安全领域。它集成了大量的漏洞利用模块(exploits)、辅助模块(auxiliary)和载荷(payloads࿰…...
进程间通信(1)——管道
1. 进程间通信简介 进程间通信(Inter-Process Communication,IPC)是指不同进程之间交换数据的机制。由于进程具有独立的地址空间,它们无法直接访问彼此的数据,因此需要IPC机制来实现信息共享、数据传递或同步操作。 …...
python基础8 单元测试
通过前面的7个章节,作者学习了python的各项基础知识,也学习了python的编译和执行。但在实际环境上,我们需要验证我们的代码功能符合我们的设计预期,所以需要结合python的单元测试类,编写单元测试代码。 Python有一个内…...
【正点原子K210连载】第七十六章 音频FFT实验 摘自【正点原子】DNK210使用指南-CanMV版指南
第七十六章 音频FFT实验 本章将介绍CanMV下FFT的应用,通过将时域采集到的音频数据通过FFT为频域。通过本章的学习,读者将学习到CanMV下控制FFT加速器进行FFT的使用。 本章分为如下几个小节: 32.1 maix.FFT模块介绍 32.2 硬件设计 32.3 程序设…...
【杂记二】git, github, vscode等
一、前言 暂时空着... 二、git 2.1 可能的疑问 1. VSCode 项目名和 GitHub 仓库名是否需要一致? 不需要一致。 VSCode 项目名(也就是你本地的文件夹名字)和 GitHub 仓库名可以不一样。 Git 是一个分布式版本控制系统,它主要关…...
《基于Spring Boot+Vue的智慧养老系统的设计与实现》开题报告
个人主页:@大数据蟒行探索者 一、研究背景及国内外研究现状 1.研究背景 根据1982年老龄问题世界大会联合国制定的标准,如果一个国家中超过65岁的老人占全国总人口的7%以上,或者超过60岁的老人占全国总人口的10%以上,那么这个国家将被定义为“老龄化社会”[1]。 随着国…...
ModBus TCP/RTU互转(主)(从)|| Modbus主动轮询下发的工业应用 || 基于智能网关的串口服务器进行Modbus数据收发的工业应用
目录 前言 一、ModBus TCP/RTU互转(从)及应用|| 1.1 举栗子 二、ModBus TCP/RTU互转(主) 2.1 举栗子 三、ModBus 主动轮询 3.1 Modbus主动轮询原理 3.2 Modbus格式上传与下发 3.2.1.设置Modbus主动轮询指令 3.2.2 设…...
【设计模式】3W 学习法深入剖析创建型模式:原理、实战与开源框架应用(含 Java 代码)
3W 学习法总结创建型模式(附 Java 代码实战及开源框架应用) 创建型模式主要关注 对象的创建,旨在提高代码的可复用性、可扩展性和灵活性。本文采用 3W 学习法(What、Why、How),深入分析 五大创建型模式&am…...
Jobby、Quarkus 和 Spring Boot对比
Jobby、Quarkus 和 Spring Boot 是三种不同的 Java 框架,各自有不同的设计目标和适用场景。以下是对它们的详细对比: 1. 设计目标 框架设计目标Jobby轻量级的任务调度框架,专注于任务调度和执行。Quarkus面向云原生和 Kubernetes 的 Java 框…...
[代码规范]1_良好的命名规范能减轻工作负担
欢迎来到啾啾的博客🐱,一个致力于构建完善的Java程序员知识体系的博客📚,记录学习的点滴,分享工作的思考、实用的技巧,偶尔分享一些杂谈💬。 欢迎评论交流,感谢您的阅读😄…...
【HarmonyOS Next之旅】DevEco Studio使用指南(三)
目录 1 -> 一体化工程迁移 1.1 -> 自动迁移 1.2 -> 手动迁移 1.2.1 -> API 10及以上历史工程迁移 1.2.2 -> API 9历史工程迁移 1 -> 一体化工程迁移 DevEco Studio从 NEXT Developer Beta1版本开始,提供开箱即用的开发体验,将SD…...
冯・诺依曼架构深度解析
一、历史溯源:计算机科学的革命性突破 1.1 前冯・诺依曼时代 在 1940 年代之前,计算机领域呈现 "百家争鸣" 的格局: 哈佛 Mark I(1944):采用分离的指令存储与数据存储ENIAC(1946&a…...
gralloc1_perform具体在干什么
gralloc1_perform 会在特定场景下通过 ioctl 调用,执行 缓存 (cache) 管理 和 内存映射 操作,确保 CPU 和 GPU 之间的数据一致性。 📌 为什么需要对 cache 进行操作? 在 Android 系统中,CPU 和 GPU 通常共享 DDR 内存…...
安装配置Anaconda,配置VSCode
文章目录 Anaconda介绍下载Anaconda安装Anaconda换源创建一个新环境conda常用命令 VSCode环境配置 记录一下笔者收集的一些资料,不喜勿喷。 Anaconda介绍 Anaconda是一个用于科学计算的Python发行版,支持 Linux, Mac, Windows系统,提供了包管…...
【愚公系列】《高效使用DeepSeek》017-知识点思维导图生成
🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…...
【量化策略】网格交易策略
【量化策略】网格交易策略 🚀量化软件开通 🚀量化实战教程 技术背景与应用场景 网格交易策略是一种基于市场波动性的自动化交易方法,适用于震荡市场。它通过在预设的价格区间内设置多个买卖点,自动执行低买高卖的操作…...
C++ 语法之函数和函数指针
在上一章中 C 语法之 指针的一些应用说明-CSDN博客 我们了解了指针变量,int *p;取变量a的地址这些。 那么函数同样也有个地址,直接输出函数名就可以得到地址,如下: #include<iostream> using namespace std; void fun() …...
网络协议抓取与分析(SSL Pinning突破)
1. 网络协议逆向基础 1.1 网络协议分析流程 graph TD A[抓包环境配置] --> B[流量捕获] B --> C{协议类型} C -->|HTTP| D[明文解析] C -->|HTTPS| E[SSL Pinning突破] D --> F[参数逆向] E --> F F --> G[协议重放与模拟] 1.1.1 关键分析目标…...
蓝桥杯真题——洛谷Day13 找规律(修建灌木)、字符串(乘法表)、队列(球票)
目录 找规律 P8781 [蓝桥杯 2022 省 B] 修剪灌木 字符串 P8723 [蓝桥杯 2020 省 AB3] 乘法表 队列 P8641 [蓝桥杯 2016 国 C] 赢球票 找规律 P8781 [蓝桥杯 2022 省 B] 修剪灌木 思路:对某个特定的点来说有向前和向后的情况,即有向前再返回到该位置…...
【2025】基于Springboot + vue实现的毕业设计选题系统
项目描述 本系统包含管理员、学生、教师三个角色。 管理员角色: 用户管理:管理系统中所有用户的信息,包括添加、删除和修改用户。 配置管理:管理系统配置参数,如上传图片的路径等。 权限管理:分配和管理…...
