2026蓝桥杯java组备战
模板(初级,三个模板随着做题的难度来记住。):
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int a = scan.nextInt(); // 读入整数
double b = scan.nextDouble(); // 读入浮点数
String s = scan.next(); // 读入字符串(不带空格)
// ... 你的逻辑
scan.close(); // 好习惯,关闭扫描器
}
}
中级:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 1. 创建Scanner对象,固定写法
Scanner scan = new Scanner(System.in);
// 2. 读取不同类型的数据
int n = scan.nextInt(); // 读取一个整数
long bigNum = scan.nextLong(); // 读取一个长整数(用于大数)
double d = scan.nextDouble(); // 读取一个双精度浮点数
float f = scan.nextFloat(); // 读取一个单精度浮点数
// 3. 读取字符串的几种方式
String s1 = scan.next(); // 读取一个单词(遇到空格、制表符、换行符就停止)
String s2 = scan.nextLine(); // 读取一整行(包括空格,直到遇到换行符)
// 注意:nextLine() 容易和 next()、nextInt() 混用产生问题,需要小心。
// 4. 判断是否还有下一个输入(在不确定输入数量时有用)
while (scan.hasNext()) {
int num = scan.nextInt();
// ... 处理逻辑
}
// 5. 关闭Scanner,释放资源(好习惯)
scan.close();
}
}
高级:
import java.util Scanner;
public class Main {
public static void main(String[] args) throws IOException {
// 使用BufferedReader和InputStreamReader,速度更快
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 读取一行,然后用split分割成字符串数组
String[] line1 = br.readLine().split(" ");
int a = Integer.parseInt(line1[0]); // 解析第一个整数
int b = Integer.parseInt(line1[1]); // 解析第二个整数
String s = br.readLine(); // 读取一行字符串
// ... 你的逻辑
br.close(); // 关闭
}
}
1.回溯法:
1.有递归就有回溯(通常在递归下面部分就是回溯的逻辑)
2.回溯搜索法(纯暴力的搜索):
组合问题:在一个集合里找出大小为某个数字的组合有多少(从 n 个数中选出 k 个,如组合、子集)
切割问题:一个字符串有几种切割方式或加特定条件,如:一个字符串如何切割才能保证它的子串都是回文串。问有几种切割方式。(字符串切割方式)
子集问题(求一个集合的所有子集)
棋盘问题(N 皇后、数独、八皇后等)
3.回溯法的万能模板:
1 void backTracking(参数){
2 if(终止条件){
3 收集结果;
4 return;
5 }
6 for(集合的元素集){
7 处理结点;
8 backTracking(结点);
9 回溯;
10 }
11 }
推荐回溯法观看:https://b23.tv/Tc4sOUD
2.DFS算法
个人理解:就是一条路走到黑,不撞南墙不回
DFS就像走迷宫的小猫!遇到岔路就选一条走到底,走不通时退回上个路口,继续找能走得通的路
1.把它想象成走迷宫:
你随机选择一个方向一直往前走。
遇到岔路时,随便选一条新路继续走。
如果走到死胡同(碰壁),就退回上一个岔路口,换一条没走过的路再试。
这个过程就是 深度优先——它优先尝试尽可能深入地探索一条路径,直到尽头再回溯。
2.实现:
通常使用 递归 或 栈(Stack) 来实现,因为这符合“先进后出”的回溯需求。
举例:
你要找到家族里所有叫“Tom”的人。
DFS做法:从爷爷开始,先顺着他的大儿子一脉查到底(查大儿子 -> 大儿子的儿子 -> ... 直到最底层),再回溯回来查爷爷的二儿子一脉,以此类推。
1.递归:
递归就是打开一个俄罗斯套娃发现里面还有一个一模一样的、更小的套娃你不断地打开,直到遇到最小的那个(终止条件),然后再一层层地把它套回去。
关键:必须有终止条件(也叫递归基),否则会无限调用导致栈溢出。
2.栈:
栈 就是你桌上用来放这些套娃的盘子。你每打开一个套娃,就把上半部分放进盘子。你想套回去时,总是从盘子的最上面(最后放进去的)拿起一个盖子。这个盘子就是“栈”。
一种 “后进先出” 的数据结构。
总结:递归是程序表现出的行为,栈是实现这种行为的基础。你可以把递归看作是一种语法糖,它背后是系统在自动为你管理一个调用栈。
3.DFS模板(java模板):
void dfs(参数:当前状态,路径,结果集 ) {
// 1. 终止条件
if (结束条件) {
记录结果/处理答案;
return;
}
// 2. 遍历所有选择
for (所有可能的选择) {
// 3. 做出选择
处理当前选择;
// 4. 递归深入
dfs(新参数);
// 5. 撤销选择(回溯)
恢复现场;
}
}
1.有点小技巧:
概念 作用 数据类型 例子(走迷宫) 当前状态 描述"我在哪",是递归函数的核心参数 通常是基本类型:int, (x,y)坐标 当前所在的坐标 (2, 3) 路径 记录"我是怎么来的",是选择序列 列表/数组:存储每一步的选择 路径:["右","右","下"] 结果集 存储"所有找到的解决方案" 列表的列表:存储所有有效路径 结果:[path1, path2, ...]
用"做选择题"的比喻来解释
想象你在做3道选择题(题目1,2,3),每道题有A、B、C三个选项。
三个概念的关系:
路径 = 你已经选的答案序列
比如: [1-A, 2-C] (第1题选了A,第2题选了C)
状态 = 现在做到哪题了,哪些题还没做
比如: 做到第3题,第1、2题已做完
结果集 = 所有完整的答题卡
比如: [[1-A,2-B,3-C], [1-A,2-C,3-B], ...]
带入实际例题(java):
题目:给定数字 [1,2,3] ,返回所有可能的排列。
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>(); // 当前路径
boolean[] used = new boolean[nums.length]; // 标记已使用的元素
dfs(nums, used, path, result);
return result;
}
private void dfs(int[] nums, boolean[] used, List<Integer> path, List<List<Integer>> result) {
// 1. 终止条件:路径长度等于数组长度
if (path.size() == nums.length) {
result.add(new ArrayList<>(path)); // 注意要new新列表!
return;
}
// 2. 遍历所有选择
for (int i = 0; i < nums.length; i++) {
// 跳过已使用的元素
if (used[i]) continue;
// 3. 做出选择
used[i] = true;
path.add(nums[i]);
// 4. 递归深入
dfs(nums, used, path, result);
// 5. 撤销选择(回溯)
path.remove(path.size() - 1);
used[i] = false;
}
}
推荐DFS算法视频:https://b23.tv/1kSyTSX
看张图放松一下大脑

3.BFS算法:
BFS是一种“地毯式”搜索,由近及远,层层推进。
BFS就是像一群小猫分头找猫饼干。每扇柜门同时闻一闻。
1.想象一下一滴墨水滴入清水中,它总是均匀地向四面八方扩散。
BFS就是这样:
从起点开始。
先访问所有距离为1步的邻居。
再访问所有距离为2步的邻居。
以此类推,直到找到目标或遍历完所有点
这里注意:BFS使用 队列(先进先出) 来保证“由近及远”的顺序。
入队:探索一个新节点时,将其所有未访问的邻居加入队列末尾。
出队:每次从队列头部取出下一个要探索的节点。
2.算法步骤
1.将起点放入队列。
从队列中取出一个节点。
检查该节点是否为目标;如果是,搜索结束。
如果不是,将该节点所有未访问的邻居标记为已访问,并加入队列。
重复步骤2-4,直到队列为空或找到目标。
看个结构图:
A - B - C
| |
D - E
从 A 开始 BFS 的访问顺序是:A → B → D → C → E
2.特点:
按层遍历(最短路径可通过 BFS 求得)
需要队列来辅助
时间复杂度:O(V + E)(顶点数 + 边数)
3.其实还可以搞个更简单的例子:
你想认识某生人谢某。
你先问你的直接朋友(第一层),认识谢某吗?
如果不认识,你再让你的每个直接朋友(第一次朋友)去问他们的直接朋友(第二层)。
这样一层层找下去,最早建立联系的那条路径,就是你们之间“关系最短”的路径。
这里记住:BFS找到的路径一定是最短路径。
4.最常用的 二维网格 BFS 模板(比如用于迷宫最短路径、岛屿数量、最短步数等问题)(python)。
from collections import deque
def bfs_grid(grid, start):
"""
:param grid: 二维网格,例如 [['0','1'], ['1','0']]
:param start: 起点坐标 (row, col)
:return: 根据题目需求返回,这里演示计算到所有点的最短步数
"""
# 网格的行数和列数
m, n = len(grid), len(grid[0])
# 1. 初始化一个队列,加入起点
queue = deque()
queue.append(start)
# 2. 初始化一个 visited 集合或距离矩阵,用于记录已访问/到达该点的步数
# 方法A(使用集合记录访问过的点): visited = set()
# visited.add(start)
# 方法B(更常用):使用一个距离矩阵,-1 表示未访问
dist = [[-1] * n for _ in range(m)]
r_start, c_start = start
dist[r_start][c_start] = 0 # 起点到自己的距离为0
# 3. 定义方向向量:代表上下左右四个方向 (dr, dc)
# 顺序不重要,但必须完整覆盖四个基本方向
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 右,下,左,上
# 如果是八连通(含对角线),可添加另外四个方向
# 4. 开始BFS遍历
while queue:
# 取出队列最前端的点
r, c = queue.popleft()
# 如果是终点,可以提前结束(非必须)
# if (r, c) == target:
# break
# 遍历当前点的所有邻居
for dr, dc in directions:
# 计算邻居的新坐标
nr, nc = r + dr, c + dc
# **关键:判断邻居坐标是否合法且可访问**
# 条件1: 新坐标在网格范围内
# 条件2: 该格子是可通过的(根据题目,比如不是墙 '1' 或障碍)
# 条件3: 这个新点没有被访问过 (dist[nr][nc] == -1)
if (0 <= nr < m and 0 <= nc < n and
grid[nr][nc] == '0' and # 假设 '0' 表示可通行的路径
dist[nr][nc] == -1):
# 标记为已访问,并记录步数
dist[nr][nc] = dist[r][c] + 1
# 将这个新点加入队列,以便从它开始继续搜索
queue.append((nr, nc))
# 返回结果,例如从起点到各点的最短距离矩阵
return dist
模板使用要点:
1.定义“通行条件”:
修改 grid[nr][nc] == '0' 这个条件来匹配你的题目。
示例:
迷宫: grid[nr][nc] == 0 (0代表路,1代表墙)
岛屿问题: grid[nr][nc] == '1' (1代表陆地,需要遍历)
2.定义“目标”:
如果找特定终点,在 while 循环内添加判断,达到时直接 break 或 return 。
3.记录路径:
如果需要记录路径而不仅仅是距离,可以创建一个 parent 矩阵,在访问邻居时记录 parent[nr][nc] = (r, c) 。
4.初始化:
务必在开始时标记起点为已访问( dist 设为0或加入 visited ),否则可能死循环。
大脑已经燃尽了,看张图放松一下

经典例题对应修改:
1.迷宫最短路径(Leetcode 1926):
通行条件: grid[nr][nc] != '#' (不是墙)
目标:出口(通常是边界格子)。
2.岛屿数量(Leetcode 200):
通行条件: grid[nr][nc] == '1' (是陆地)
调用一次BFS会标记整个相连的岛屿为已访问。主函数中遍历所有格子,遇到未访问的陆地就调用BFS,计数+1。
3.腐烂的橘子(Leetcode 994):
初始队列加入所有腐烂橘子的坐标。
通行条件: grid[nr][nc] == 1 (是新鲜橘子)。
5.这里加个BFS的java模板
void bfs(起始点) {
// 1. 创建队列和visited集合
Queue<节点类型> queue = new LinkedList<>();
Set<节点状态> visited = new HashSet<>(); // 或 boolean[][] visited
// 2. 起点入队并标记
queue.offer(起始点);
visited.add(起始状态);
int level = 0; // 记录层数(如果需要)
// 3. BFS循环
while (!queue.isEmpty()) {
int size = queue.size(); // 当前层的节点数
// 遍历当前层的所有节点
for (int i = 0; i < size; i++) {
// 出队
节点类型 curr = queue.poll();
// 判断是否到达目标
if (isTarget(curr)) {
return level; // 或处理结果
}
// 遍历所有邻居/下一步选择
for (节点类型 neighbor : getNeighbors(curr)) {
// 检查是否访问过
if (!visited.contains(neighbor状态)) {
// 入队并标记
queue.offer(neighbor);
visited.add(neighbor状态);
}
}
}
level++; // 层数增加
}
return -1; // 未找到目标
}
实战例子:二叉树层序遍历
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
if (root == null) return result;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int levelSize = queue.size();
List<Integer> levelNodes = new ArrayList<>();
for (int i = 0; i < levelSize; i++) {
TreeNode node = queue.poll();
levelNodes.add(node.val);
// 添加左右子节点
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
result.add(levelNodes);
}
return result;
}
推荐BFS算法视频:https://b23.tv/VTKY6iJ
4.最短路径
1.问题本质
在地图上找到从A点到B点的最省钱(或最省时间)的走法。
把问题变成日常例子:
想象你要从家去学校,有好多条路可以走:
小路:近但是堵车(花时间)
大路:远但是畅通(省时间)
高速公路:最快但要交过路费(花钱)
最短路径算法就是帮你算出:哪条路总体“代价”最小?
2.三种算法:
这里有小技巧:
大部分题用Dijkstra- 就像生活中大部分导航都用Dijkstra原理2.
如果题目说“每一步代价一样”,用BFS- 比如走迷宫,求最少步数
如果地点很少但需要查很多次,用Floyd- 比如10个城市之间互相怎么走最近
最简单的心得:
有数字代价 → 想Dijkstra
只数步数 → 想BFS
地点很少 → 想Floyd
1. Dijkstra算法(最常用)→ “保守派找路法”
做法:从家门口开始,一步一步往外探索,每次都先走当前已知的最近的路。
好比:你拿个小本本,先记下从家到小区门口要5分钟,然后发现从小区门口到公交站要3分钟...这样一步步推下去,保证每次扩展的都是当前最近的点。
缺点:如果某条路要收“过路费”(负权值),这个方法会算错。
什么时候用:绝大多数情况,因为现实中距离、时间都是正数。
2. Floyd算法 → “上帝视角找路法”
做法:直接把全市所有地点之间的最短距离都算出来,存在一张大表里。
好比:你打开手机地图,它已经提前算好了所有地方之间的最短路径,你问任何两个地方它都能秒答。
缺点:如果城市太大(地点太多),算这张表会非常慢。
什么时候用:当需要反复查询不同地点之间的最短路径时,且城市规模不大。
3. BFS(广度优先搜索)→ “数步数找路法”
做法:不管路的实际长度,只数“转弯次数”或“经过的路口数”。
好比:别人问你怎么走,你说“直走3个路口,左转再走2个路口”,而不关心每个路口之间是多远。
什么时候用:当每条路的“代价”都相同时(比如走格子游戏,每一步代价都是1)。
我知道你眼睛已经疲惫了,放张图休息一下

3.Dijkstra算法(步步为营的探索法)
1.想象一下
你在一个陌生的巨大迷宫里,要从起点走到终点。这个迷宫的特点是:
每条通道的长度不一样
你只能看到当前位置相邻的通道
你的目标是找到总长度最短的路线
Dijkstra的做法就像这样:
从起点开始,拿个小本本记录到每个地方的已知最短距离,每次只走“当前已知最近”的路,走到新地方后,更新这个小本本,重复直到找到终点。
2.举个例子
假设我们要从A点走到E点:
A
/ \
1 3/ \
B---2--- C
| |4 1
| |
D---1---E
第一步:初始化
从A出发,A到A的距离是0
其他点暂时记作“无穷远”
已知距离:A(0), B(∞), C(∞), D(∞), E(∞)
第二步:探索最近的邻居
从A出发,有两条路:
A→B:距离1
A→C:距离3
选择最近的B点(距离1),确定A→B的最短距离就是1
第三步:从B点继续探索
从B点可以看到:
B→D:距离4,所以A→B→D = 1+4 = 5
更新已知距离:A(0), B(1), C(3), D(5), E(∞)
第四步:在未确定的点中选最近的
现在未确定的点有:C(3), D(5), E(∞)
选择C点(距离3),确定A→C的最短距离是3
第五步:从C点继续探索
从C点可以看到:
C→E:距离1,所以A→C→E = 3+1 = 4
更新已知距离:A(0), B(1), C(3), D(5), E(4)
第六步:选择下一个最近的点
未确定的点:D(5), E(4)
选择E点(距离4),发现E就是终点,算法结束!
最终结果:最短路径是A→C→E,总距离为4
3.基础模板(邻接表 + 优先队列)java
import java.util.*;
public class DijkstraTemplate {
// 边的定义(可选,用于构建图)
static class Edge {
int to; // 目标节点
int weight; // 边权
Edge(int to, int weight) {
this.to = to;
this.weight = weight;
}
}
/**
* 堆优化Dijkstra算法
* @param graph 图的邻接表表示,graph[i]包含从节点i出发的所有边
* @param start 起始节点
* @return dist数组,dist[i]表示从start到i的最短距离
*/
public static int[] dijkstra(List<Edge>[] graph, int start) {
int n = graph.length;
int[] dist = new int[n];
Arrays.fill(dist, Integer.MAX_VALUE); // 初始化为无穷大
dist[start] = 0;
// 优先队列,按距离从小到大排序
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[1] - b[1]);
pq.offer(new int[]{start, 0});
while (!pq.isEmpty()) {
int[] curr = pq.poll();
int u = curr[0]; // 当前节点
int currDist = curr[1]; // 当前距离
// 如果当前距离大于已记录的最短距离,跳过(重要优化)
if (currDist > dist[u]) {
continue;
}
// 遍历所有邻居
for (Edge edge : graph[u]) {
int v = edge.to;
int w = edge.weight;
int newDist = currDist + w;
// 如果找到更短的路径
if (newDist < dist[v]) {
dist[v] = newDist;
pq.offer(new int[]{v, newDist});
}
}
}
return dist;
}
}
不要急,看图放松

4.网格地图专用模板
import java.util.*;
public class GridDijkstra {
// 四个方向:上、右、下、左
static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};
/**
* 网格地图的Dijkstra
* @param grid 网格,grid[i][j]表示该格子的代价
* @return 从(0,0)到(n-1,m-1)的最短路径和
*/
public static int dijkstraGrid(int[][] grid) {
int n = grid.length, m = grid[0].length;
int[][] dist = new int[n][m];
// 初始化距离矩阵
for (int i = 0; i < n; i++) {
Arrays.fill(dist[i], Integer.MAX_VALUE);
}
dist[0][0] = grid[0][0];
// 优先队列:[x, y, distance]
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[2] - b[2]);
pq.offer(new int[]{0, 0, grid[0][0]});
while (!pq.isEmpty()) {
int[] curr = pq.poll();
int x = curr[0], y = curr[1], currDist = curr[2];
// 如果当前距离大于已记录距离,跳过
if (currDist > dist[x][y]) continue;
// 如果是终点,可以直接返回(优化)
if (x == n-1 && y == m-1) {
return currDist;
}
// 遍历四个方向
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
int newDist = currDist + grid[nx][ny];
if (newDist < dist[nx][ny]) {
dist[nx][ny] = newDist;
pq.offer(new int[]{nx, ny, newDist});
}
}
}
}
return dist[n-1][m-1];
}
public static void main(String[] args) {
int[][] grid = {
{1, 3, 1},
{1, 5, 1},
{4, 2, 1}
};
int result = dijkstraGrid(grid);
System.out.println("最短路径和: " + result); // 输出: 7
}
}
推荐Dijkstra视频:https://b23.tv/XwIFpWE
5.java排序算法
6.java数组切割:
看张照片放松

7.java矩形面积:
8.java蜗牛:
9.java合并区域:
10.java买二赠一:
11.java阶乘求和:
12.java进制转换:
13.java枚举:
14.蓝桥javaDP:
15.蓝桥java优先排列:
16.蓝桥java前缀和:
17.蓝桥java求最大公约数:
更多推荐






所有评论(0)