蓝桥杯 Java B 组之函数定义与递归入门

devtools/2025/2/12 18:02:42/

一、Java 函数(方法)基础

1. 什么是函数?

函数(方法)是 一段可复用的代码块,通过 函数调用 执行,并可返回值。在 Java 里,函数也被叫做方法,它是一段具有特定功能的、可重复使用的代码块。函数能够把复杂的问题分解成小的子问题,提升代码的可读性与可维护性。

Java 方法的格式:

修饰符 返回值类型 函数名(参数列表)

 { // 函数体 return 返回值; // 如果返回值类型是 void,则不需要 return 语句

 }

  • 修饰符:像 publicprivatestatic 等,用于限定函数的访问权限和特性。
  • 返回值类型:函数执行完毕后返回结果的数据类型,若不返回任何值,使用 void
  • 函数名:给函数起的名称,要遵循命名规范。
  • 参数列表:传递给函数的参数,多个参数用逗号分隔。
  • 函数体:实现具体功能的代码。
  • 返回值:使用 return 语句返回函数的执行结果。


2. Java 方法定义

(1)无参数无返回值

public static void sayHello() {

    System.out.println("Hello, 蓝桥杯!");

}

调用:

sayHello();

(2)有参数有返回值

public static int add(int a, int b) {

    return a + b;

}

调用:

int sum = add(5, 3);  // sum = 8


3. 递归函数

递归(Recursion)是函数自己调用自己

1. 递归的概念

递归是指在函数的定义中使用函数自身的方法。递归包含两个关键要素:

基线条件(终止条件):能够直接得出结果,不再进行递归调用的条件,避免无限递归。

递归条件:函数调用自身来解决规模更小的子问题。

通常用于:

  • 数学计算(如阶乘、斐波那契数列)
  • 问题拆解(如汉诺塔、深度优先搜索)


二、递归的基本概念

1. 递归的两部分

(1)基准情况(终止条件):防止无限递归
(2)递归关系(拆分问题):将大问题分解成小问题

示例:递归求 n!

java">public static int factorial(int n) {if (n == 0 || n == 1) {  // 终止条件return 1;}return n * factorial(n - 1);  // 递归调用}调用:System.out.println(factorial(5));  // 5! = 120


三、练习 1:递归求阶乘

题目描述

输入 n,求 n!(n 的阶乘)。

输入示例

5

输出示例

120

Java 代码

java">import java.util.Scanner;public class Main {public static int factorial(int n) {if (n == 0 || n == 1) {return 1;}return n * factorial(n - 1);}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();System.out.println(factorial(n));}}

考点

  • 递归终止条件:n == 0 || n == 1
  • 递归调用:n * factorial(n - 1)
  • 时间复杂度 O(n)

⚠️ 易错点

  • 没有终止条件,导致无限递归
  • n 太大时可能导致栈溢出(StackOverflowError


四、练习 2:递归求斐波那契数列

1. 斐波那契数列定义

F(n)=F(n−1)+F(n−2)

其中:

  • F(0) = 0
  • F(1) = 1


题目描述

输入 n,输出斐波那契数列的第 n 项。

输入示例

6

输出示例

8


Java 代码

java">import java.util.Scanner;public class Main {public static int fibonacci(int n) {if (n == 0) {return 0;} else if (n == 1) {return 1;}return fibonacci(n - 1) + fibonacci(n - 2);}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();System.out.println(fibonacci(n));}}

✅代码解释:

当 n 为 0 时返回 0,当 n 为 1 时返回 1,这是基线条件。

当 n 大于 1 时,函数调用自身 fibonacci(n - 1) 和 fibonacci(n - 2) 并将结果相加,这是递归条件。

 考点

  • 递归终止条件:n == 0 或 n == 1
  • 递归公式:F(n) = F(n-1) + F(n-2)
  • 时间复杂度 O(2^n)(指数级,效率低)

⚠️ 易错点

  • 直接递归 O(2^n) 太慢,n 较大时严重超时
  • 优化方案使用数组存储已计算值(记忆化递归)


五、练习 3:汉诺塔问题

1. 题目介绍

汉诺塔问题:汉诺塔问题是一个经典的递归问题,目标是把所有盘子从一根柱子移动到另一根柱子,每次只能移动一个盘子,且大盘子不能放在小盘子上面。

  1. 有 n 个盘子,从 A 移到 C,借助 B
  2. 规则
    • 一次只能移动一个盘子
    • 不能将大盘子放在小盘子上


输入

3

输出

Move disk 1 from A to C

Move disk 2 from A to B

Move disk 1 from C to B

Move disk 3 from A to C

Move disk 1 from B to A

Move disk 2 from B to C

Move disk 1 from A to C


Java 代码

java">import java.util.Scanner;public class Main {public static void hanoi(int n, char from, char aux, char to) {if (n == 1) {System.out.println("Move disk 1 from " + from + " to " + to);return;}hanoi(n - 1, from, to, aux);System.out.println("Move disk " + n + " from " + from + " to " + to);hanoi(n - 1, aux, from, to);}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();hanoi(n, 'A', 'B', 'C');}}

代码解释

  • 当 n 为 1 时,直接将盘子从源柱子移动到目标柱子,这是基线条件。
  • 当 n 大于 1 时,先把 n - 1 个盘子从源柱子借助目标柱子移动到辅助柱子,再把第 n 个盘子从源柱子移动到目标柱子,最后把 n - 1 个盘子从辅助柱子借助源柱子移动到目标柱子,这是递归条件。

考点

  • 递归拆解
    1. 移动 n-1 个盘子 A → B
    2. 移动第 n 个盘子 A → C
    3. 移动 n-1 个盘子 B → C
  • 时间复杂度 O(2^n)

⚠️ 易错点

  • if (n == 1) 不能少,否则死循环
  • hanoi(n - 1, from, to, aux) 和 hanoi(n - 1, aux, from, to) 位置不能搞错


六、蓝桥杯递归常考点

考点

典型题目

难点

递归求阶乘

n! = n * (n-1)!

终止条件 n == 1

递归求斐波那契

F(n) = F(n-1) + F(n-2)

优化记忆化递归

汉诺塔

递归移动盘子

移动顺序和 O(2^n)


七、递归的易错点总结

1. 基线条件缺失或错误

如果基线条件不正确或者缺失,会导致无限递归,最终引发栈溢出异常。

2. 重复计算问题

在递归过程中,可能会出现大量的重复计算,比如斐波那契数列递归实现,会使时间复杂度呈指数级增长。可以使用记忆化搜索或迭代方法来优化。

3. 递归深度过大

当递归深度过大时,会占用大量的栈空间,容易导致栈溢出。要注意递归深度的控制,必要时转换为迭代实现。

递归核心思想

1. 递归三要素

终止条件(Base Case):递归何时结束。

递归步骤(Recursive Step):如何将问题分解为更小的子问题。

问题规模缩小:每次递归调用应使问题更接近终止条件。


http://www.ppmy.cn/devtools/158278.html

相关文章

ESP32S3基于espidf ADC使用

ESP32S3基于espidf ADC使用 官方在线文档介绍模数转换器:https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32s3/api-reference/peripherals/adc_oneshot.html🔖espidf版本:v5.4 模数转换器 (ADC)转换方式: 模数转换…

详解Redis中lua脚本和事务

In learning knowledge, one should be good at thinking, thinking, and thinking again. —-Albert Einstein 引言 Lua脚本的原子性和事务的ACID特性想必大家都很熟悉,本篇文章将从性能表现和原理帮助我们快速理解他们 基本概念 1. Redis Lua 脚本 从 2.6 版本…

2526考研资料分享 百度网盘

通过网盘分享的文件:01、2026【考研数学】 链接:https://pan.baidu.com/s/1PwMzp_yCYqjBqa7492mP3w?pwd98wg 提取码:98wg--来自百度网盘超级会员v3的分享 通过网盘分享的文件:01、2026【考研政治】 链接:https://pan.baidu.com/s/1PwMzp_yCYqjBqa7492…

flutter isolate到底是啥

在 Flutter 中,Isolate 是一种实现多线程编程的机制,下面从概念、工作原理、使用场景、使用示例几个方面详细介绍: 概念 在 Dart 语言(Flutter 开发使用的编程语言)里,每个 Dart 程序至少运行在一个 Isol…

【Pytorch实战教程】让数据飞轮转起来:PyTorch Dataset与Dataloader深度指南

文章目录 让数据飞轮转起来:PyTorch Dataset与Dataloader深度指南一、为什么需要数据管理组件?二、Dataset:数据集的编程接口2.1 自定义Dataset三要素2.2 实战案例:图像分类数据集三、Dataloader:高效数据流水线3.1 核心参数解析3.2 数据流可视化3.3 多卡训练支持四、综合…

【C++高并发服务器WebServer】-17:阻塞/非阻塞和同步/异步、五种IO模型、Web服务器

本文目录 一、阻塞/非阻塞、同步/异步1.1 辨析1.2 异步io接口 二、五种IO模型2.1 阻塞 blocking 模型2.2 非阻塞 NIO 模型2.3 IO多路复用2.4 信号驱动Signal-driven2.5 异步 三、Web Sever 网页服务器3.1 HTTP的请求响应步骤3.2 HTTP请求与响应报文格式3.3 HTTP请求方法3.4 HTT…

element-plus 解决el-dialog背后的页面滚动问题,及其内容有下拉框出现错位问题

这个问题通常是因为 el‑dialog 默认会锁定 body 的滚动&#xff08;通过给 body 添加隐藏滚动条的样式&#xff09;&#xff0c;从而导致页面在打开对话框时跳转到顶部。解决方法是在使用 el‑dialog 时禁用锁定滚动功能。 <el-dialogv-model"dialogVisible":lo…

数据结构 单链表的模拟实现

一、链表的定义 线性表的链式存储就是链表。 它是将元素存储在物理上任意的存储单元中&#xff0c;由于⽆法像顺序表⼀样通过下标保证数据元素之间的逻辑关系&#xff0c;链式存储除了要保存数据元素外&#xff0c;还需额外维护数据元素之间的逻辑关系&#xff0c;这两部分信息…