class062 宽度优先遍历及其扩展【算法】

class062 宽度优先遍历及其扩展【算法】

算法讲解062【必备】宽度优先遍历及其扩展

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

code1 1162. 地图分析

// 地图分析
// 你现在手里有一份大小为 n x n 的 网格 grid
// 上面的每个 单元格 都用 0 和 1 标记好了其中 0 代表海洋,1 代表陆地。
// 请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的
// 并返回该距离。如果网格上只有陆地或者海洋,请返回 -1。
// 我们这里说的距离是「曼哈顿距离」( Manhattan Distance):
// (x0, y0) 和 (x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1| 。
// 测试链接 : https://leetcode.cn/problems/as-far-from-land-as-possible/

多源bfs

package class062;

// 地图分析
// 你现在手里有一份大小为 n x n 的 网格 grid
// 上面的每个 单元格 都用 0 和 1 标记好了其中 0 代表海洋,1 代表陆地。
// 请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的
// 并返回该距离。如果网格上只有陆地或者海洋,请返回 -1。
// 我们这里说的距离是「曼哈顿距离」( Manhattan Distance):
// (x0, y0) 和 (x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1| 。
// 测试链接 : https://leetcode.cn/problems/as-far-from-land-as-possible/
public class Code01_AsFarFromLandAsPossible {

	public static int MAXN = 101;

	public static int MAXM = 101;

	public static int[][] queue = new int[MAXN * MAXM][2];

	public static int l, r;

	public static boolean[][] visited = new boolean[MAXN][MAXM];

	// 0:上,1:右,2:下,3:左
	public static int[] move = new int[] { -1, 0, 1, 0, -1 };
	//                                      0  1  2  3   4
	//                                               i
	// (x,y)  i来到0位置 : x + move[i], y + move[i+1] -> x - 1, y
	// (x,y)  i来到1位置 : x + move[i], y + move[i+1] -> x, y + 1
	// (x,y)  i来到2位置 : x + move[i], y + move[i+1] -> x + 1, y
	// (x,y)  i来到3位置 : x + move[i], y + move[i+1] -> x, y - 1

	public static int maxDistance(int[][] grid) {
		l = r = 0;
		int n = grid.length;
		int m = grid[0].length;
		int seas = 0;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (grid[i][j] == 1) {
					visited[i][j] = true;
					queue[r][0] = i;
					queue[r++][1] = j;
				} else {
					visited[i][j] = false;
					seas++;
				}
			}
		}
		if (seas == 0 || seas == n * m) {
			return -1;
		}
		int level = 0;
		while (l < r) {
			level++;
			int size = r - l;
			for (int k = 0, x, y, nx, ny; k < size; k++) {
				x = queue[l][0];
				y = queue[l++][1];
				for (int i = 0; i < 4; i++) {
					// 上、右、下、左
					nx = x + move[i];
					ny = y + move[i + 1];
					if (nx >= 0 && nx < n && ny >= 0 && ny < m && !visited[nx][ny]) {
						visited[nx][ny] = true;
						queue[r][0] = nx;
						queue[r++][1] = ny;
					}
				}
			}
		}
		return level - 1;
	}

}

code2 691. 贴纸拼词

// 贴纸拼词
// 我们有 n 种不同的贴纸。每个贴纸上都有一个小写的英文单词。
// 您想要拼写出给定的字符串 target ,方法是从收集的贴纸中切割单个字母并重新排列它们
// 如果你愿意,你可以多次使用每个贴纸,每个贴纸的数量是无限的。
// 返回你需要拼出 target 的最小贴纸数量。如果任务不可能,则返回 -1
// 注意:在所有的测试用例中,所有的单词都是从 1000 个最常见的美国英语单词中随机选择的
// 并且 target 被选择为两个随机单词的连接。
// 测试链接 : https://leetcode.cn/problems/stickers-to-spell-word/

package class062;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;

// 贴纸拼词
// 我们有 n 种不同的贴纸。每个贴纸上都有一个小写的英文单词。
// 您想要拼写出给定的字符串 target ,方法是从收集的贴纸中切割单个字母并重新排列它们
// 如果你愿意,你可以多次使用每个贴纸,每个贴纸的数量是无限的。
// 返回你需要拼出 target 的最小贴纸数量。如果任务不可能,则返回 -1
// 注意:在所有的测试用例中,所有的单词都是从 1000 个最常见的美国英语单词中随机选择的
// 并且 target 被选择为两个随机单词的连接。
// 测试链接 : https://leetcode.cn/problems/stickers-to-spell-word/
public class Code02_StickersToSpellWord {

	public static int MAXN = 401;

	public static String[] queue = new String[MAXN];

	public static int l, r;

	// 下标0 -> a
	// 下标1 -> b
	// 下标2 -> c
	// ...
	// 下标25 -> z
	public static ArrayList<ArrayList<String>> graph = new ArrayList<>();

	static {
		for (int i = 0; i < 26; i++) {
			graph.add(new ArrayList<>());
		}
	}

	public static HashSet<String> visited = new HashSet<>();

	// 宽度优先遍历的解法
	// 也可以使用动态规划
	// 后续课程会有动态规划专题讲解
	public static int minStickers(String[] stickers, String target) {
		for (int i = 0; i < 26; i++) {
			graph.get(i).clear();
		}
		visited.clear();
		for (String str : stickers) {
			str = sort(str);
			for (int i = 0; i < str.length(); i++) {
				if (i == 0 || str.charAt(i) != str.charAt(i - 1)) {
					graph.get(str.charAt(i) - 'a').add(str);
				}
			}
		}
		target = sort(target);
		visited.add(target);
		l = r = 0;
		queue[r++] = target;
		int level = 1;
		// 使用队列的形式是整层弹出
		while (l < r) {
			int size = r - l;
			for (int i = 0; i < size; i++) {
				String cur = queue[l++];
				for (String s : graph.get(cur.charAt(0) - 'a')) {
					String next = next(cur, s);
					if (next.equals("")) {
						return level;
					} else if (!visited.contains(next)) {
						visited.add(next);
						queue[r++] = next;
					}
				}
			}
			level++;
		}
		return -1;
	}

	public static String sort(String str) {
		char[] s = str.toCharArray();
		Arrays.sort(s);
		return String.valueOf(s);
	}

	public static String next(String t, String s) {
		StringBuilder builder = new StringBuilder();
		for (int i = 0, j = 0; i < t.length();) {
			if (j == s.length()) {
				builder.append(t.charAt(i++));
			} else {
				if (t.charAt(i) < s.charAt(j)) {
					builder.append(t.charAt(i++));
				} else if (t.charAt(i) > s.charAt(j)) {
					j++;
				} else {
					i++;
					j++;
				}
			}
		}
		return builder.toString();
	}

}

code3 2290. 到达角落需要移除障碍物的最小数目

// 到达角落需要移除障碍物的最小数目
// 给你一个下标从 0 开始的二维整数数组 grid ,数组大小为 m x n
// 每个单元格都是两个值之一:
// 0 表示一个 空 单元格,
// 1 表示一个可以移除的 障碍物
// 你可以向上、下、左、右移动,从一个空单元格移动到另一个空单元格。
// 现在你需要从左上角 (0, 0) 移动到右下角 (m - 1, n - 1)
// 返回需要移除的障碍物的最小数目
// 测试链接 : https://leetcode.cn/problems/minimum-obstacle-removal-to-reach-corner/

01bfs模板

package class062;

import java.util.ArrayDeque;

// 到达角落需要移除障碍物的最小数目
// 给你一个下标从 0 开始的二维整数数组 grid ,数组大小为 m x n
// 每个单元格都是两个值之一:
// 0 表示一个 空 单元格,
// 1 表示一个可以移除的 障碍物
// 你可以向上、下、左、右移动,从一个空单元格移动到另一个空单元格。
// 现在你需要从左上角 (0, 0) 移动到右下角 (m - 1, n - 1) 
// 返回需要移除的障碍物的最小数目
// 测试链接 : https://leetcode.cn/problems/minimum-obstacle-removal-to-reach-corner/
public class Code03_MinimumObstacleRemovalToReachCorner {

	public static int minimumObstacles(int[][] grid) {
		int[] move = { -1, 0, 1, 0, -1 };
		int m = grid.length;
		int n = grid[0].length;
		int[][] distance = new int[m][n];
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				distance[i][j] = Integer.MAX_VALUE;
			}
		}
		ArrayDeque<int[]> deque = new ArrayDeque<>();
		deque.addFirst(new int[] { 0, 0 });
		distance[0][0] = 0;
		while (!deque.isEmpty()) {
			int[] record = deque.pollFirst();
			int x = record[0];
			int y = record[1];
			if (x == m - 1 && y == n - 1) {
				return distance[x][y];
			}
			for (int i = 0; i < 4; i++) {
				int nx = x + move[i], ny = y + move[i + 1];
				if (nx >= 0 && nx < m && ny >= 0 && ny < n &&
						distance[x][y] + grid[nx][ny] < distance[nx][ny]) {
					distance[nx][ny] = distance[x][y] + grid[nx][ny];
					if (grid[nx][ny] == 0) {
						deque.addFirst(new int[] { nx, ny });
					} else {
						deque.addLast(new int[] { nx, ny });
					}
				}
			}
		}
		return -1;
	}

}

code4 1368. 使网格图至少有一条有效路径的最小代价

// 使网格图至少有一条有效路径的最小代价
// 给你一个 m * n 的网格图 grid 。 grid 中每个格子都有一个数字
// 对应着从该格子出发下一步走的方向。 grid[i][j] 中的数字可能为以下几种情况:
// 1 ,下一步往右走,也就是你会从 grid[i][j] 走到 grid[i][j + 1]
// 2 ,下一步往左走,也就是你会从 grid[i][j] 走到 grid[i][j - 1]
// 3 ,下一步往下走,也就是你会从 grid[i][j] 走到 grid[i + 1][j]
// 4 ,下一步往上走,也就是你会从 grid[i][j] 走到 grid[i - 1][j]
// 注意网格图中可能会有 无效数字 ,因为它们可能指向 grid 以外的区域
// 一开始,你会从最左上角的格子 (0,0) 出发
// 我们定义一条 有效路径 为从格子 (0,0) 出发,每一步都顺着数字对应方向走
// 最终在最右下角的格子 (m - 1, n - 1) 结束的路径
// 有效路径 不需要是最短路径
// 你可以花费1的代价修改一个格子中的数字,但每个格子中的数字 只能修改一次
// 请你返回让网格图至少有一条有效路径的最小代价
// 测试链接 : https://leetcode.cn/problems/minimum-cost-to-make-at-least-one-valid-path-in-a-grid/

01bfs

code5 407. 接雨水 II

// 二维接雨水
// 给你一个 m * n 的矩阵,其中的值均为非负整数,代表二维高度图每个单元的高度
// 请计算图中形状最多能接多少体积的雨水。
// 测试链接 : https://leetcode.cn/problems/trapping-rain-water-ii/

bfs+优先队列

package class062;

import java.util.PriorityQueue;

// 二维接雨水
// 给你一个 m * n 的矩阵,其中的值均为非负整数,代表二维高度图每个单元的高度
// 请计算图中形状最多能接多少体积的雨水。
// 测试链接 : https://leetcode.cn/problems/trapping-rain-water-ii/
public class Code05_TrappingRainWaterII {

	public static int trapRainWater(int[][] height) {
		int[] move = new int[] { -1, 0, 1, 0, -1 };
		int n = height.length;
		int m = height[0].length;
		// 0 : 行
		// 1 : 列
		// 2 : 水线
		PriorityQueue<int[]> heap = new PriorityQueue<>((a, b) -> a[2] - b[2]);
		boolean[][] visited = new boolean[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (i == 0 || i == n - 1 || j == 0 || j == m - 1) {
					// 边界
					heap.add(new int[] { i, j, height[i][j] });
					visited[i][j] = true;
				} else {
					visited[i][j] = false;
				}
			}
		}
		int ans = 0;
		while (!heap.isEmpty()) {
			int[] record = heap.poll();
			int r = record[0];
			int c = record[1];
			int w = record[2];
			ans += w - height[r][c];
			for (int i = 0, nr, nc; i < 4; i++) {
				nr = r + move[i];
				nc = c + move[i + 1];
				if (nr >= 0 && nr < n && nc >= 0 && nc < m && !visited[nr][nc]) {
					heap.add(new int[] { nr, nc, Math.max(height[nr][nc], w) });
					visited[nr][nc] = true;
				}
			}
		}
		return ans;
	}

}

code6

// 单词接龙 II
// 按字典 wordList 完成从单词 beginWord 到单词 endWord 转化
// 一个表示此过程的 转换序列 是形式上像
// beginWord -> s1 -> s2 -> … -> sk 这样的单词序列,并满足:
// 每对相邻的单词之间仅有单个字母不同
// 转换过程中的每个单词 si(1 <= i <= k)必须是字典 wordList 中的单词
// 注意,beginWord 不必是字典 wordList 中的单词
// sk == endWord
// 给你两个单词 beginWord 和 endWord ,以及一个字典 wordList
// 请你找出并返回所有从 beginWord 到 endWord 的 最短转换序列
// 如果不存在这样的转换序列,返回一个空列表
// 每个序列都应该以单词列表 [beginWord, s1, s2, …, sk] 的形式返回
// 测试链接 : https://leetcode.cn/problems/word-ladder-ii/

bfs+深度优先队列,生成路径

package class062;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

// 单词接龙 II
// 按字典 wordList 完成从单词 beginWord 到单词 endWord 转化
// 一个表示此过程的 转换序列 是形式上像 
// beginWord -> s1 -> s2 -> ... -> sk 这样的单词序列,并满足:
// 每对相邻的单词之间仅有单个字母不同
// 转换过程中的每个单词 si(1 <= i <= k)必须是字典 wordList 中的单词
// 注意,beginWord 不必是字典 wordList 中的单词
// sk == endWord
// 给你两个单词 beginWord 和 endWord ,以及一个字典 wordList
// 请你找出并返回所有从 beginWord 到 endWord 的 最短转换序列
// 如果不存在这样的转换序列,返回一个空列表
// 每个序列都应该以单词列表 [beginWord, s1, s2, ..., sk] 的形式返回
// 测试链接 : https://leetcode.cn/problems/word-ladder-ii/
public class Code06_WordLadderII {

	// 单词表 : list -> hashSet
	public static HashSet<String> dict;

	public static HashSet<String> curLevel = new HashSet<>();

	public static HashSet<String> nextLevel = new HashSet<>();

	// 反向图
	public static HashMap<String, ArrayList<String>> graph = new HashMap<>();

	// 记录路径,当生成一条有效路的时候,拷贝进ans!
	public static LinkedList<String> path = new LinkedList<>();

	public static List<List<String>> ans = new ArrayList<>();

	public static void build(List<String> wordList) {
		dict = new HashSet<>(wordList);
		graph.clear();
		ans.clear();
		curLevel.clear();
		nextLevel.clear();
	}

	public static List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
		build(wordList);
		if (!dict.contains(endWord)) {
			return ans;
		}
		if (bfs(beginWord, endWord)) {
			dfs(endWord, beginWord);
		}
		return ans;
	}

	// begin -> end ,一层层bfs去,建图
	// 返回值:真的能找到end,返回true;false
	public static boolean bfs(String begin, String end) {
		boolean find = false;
		curLevel.add(begin);
		while (!curLevel.isEmpty()) {
			dict.removeAll(curLevel);
			for (String word : curLevel) {
				// word : 去扩
				// 每个位置,字符a~z,换一遍!检查在词表中是否存在
				// 避免,加工出自己
				char[] w = word.toCharArray();
				for (int i = 0; i < w.length; i++) {
					char old = w[i];
					for (char ch = 'a'; ch <= 'z'; ch++) {
						w[i] = ch;
						String str = String.valueOf(w);
						if (dict.contains(str) && !str.equals(word)) {
							if (str.equals(end)) {
								find = true;
							}
							graph.putIfAbsent(str, new ArrayList<>());
							graph.get(str).add(word);
							nextLevel.add(str);
						}
					}
					w[i] = old;
				}
			}
			if (find) {
				return true;
			} else {
				HashSet<String> tmp = curLevel;
				curLevel = nextLevel;
				nextLevel = tmp;
				nextLevel.clear();
			}
		}
		return false;
	}

	public static void dfs(String word, String aim) {
		path.addFirst(word);
		if (word.equals(aim)) {
			ans.add(new ArrayList<>(path));
		} else if (graph.containsKey(word)) {
			for (String next : graph.get(word)) {
				dfs(next, aim);
			}
		}
		path.removeFirst();
	}

}

2023-12-8 21:13:01

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

初识Linux:权限(2)

目录 权限 用户&#xff08;角色&#xff09; 文件权限属性 文件的权限属性&#xff1a; 有无权限的区别&#xff1a; 身份匹配&#xff1a; 拥有者、所属组的修改&#xff1a; 八进制的转化&#xff1a; 文件的类型&#xff1a; x可执行权限为什么不能执行&#xf…

flstudio21破解汉化版2024最新水果编曲使用教程

​ 如果你一直梦想制作自己的音乐(无论是作为一名制作人还是艺术家)&#xff0c;你可能会想你出生在这个时代是你的幸运星。这个水果圈工作室和上一版之间的改进水平确实令人钦佩。这仅仅是FL Studio 21所提供的皮毛。你的音乐项目的选择真的会让你大吃一惊。你以前从未有过这…

3_CSS层叠样式表基础

第3章-CSS层叠样式表基础 学习目标(Objective) 掌握标签选择器的使用掌握类选择器的使用了解id选择器和通配符选择器掌握font属性和color属性的应用 1.HTML的局限性 如果要改变下高度或者变一个颜色&#xff0c;就需要大量重复操作 总结&#xff1a; HTML满足不了设计者的需…

初识优先级队列与堆

1.优先级队列 由前文队列queue可知&#xff0c;队列是一种先进先出(FIFO)的数据结构&#xff0c;但有些情况下&#xff0c;操作的数据可能带有优先级&#xff0c;一般出队列时&#xff0c;可能需要优先级高的元素先出队列&#xff0c;在此情况下&#xff0c;使用队列queue显然不…

git clone 命令

git clone 是一个用于克隆&#xff08;clone&#xff09;远程 Git 仓库到本地的命令。 git clone 可以将一个远程 Git 仓库拷贝到本地&#xff0c;让自己能够查看该项目&#xff0c;或者进行修改。 git clone 命令&#xff0c;你可以复制远程仓库的所有代码和历史记录&#xf…

python基于轻量级GhostNet模型开发构建23种常见中草药图像识别系统

轻量级识别模型在我们前面的博文中已经有过很多实践了&#xff0c;感兴趣的话可以自行移步阅读&#xff1a; 《移动端轻量级模型开发谁更胜一筹&#xff0c;efficientnet、mobilenetv2、mobilenetv3、ghostnet、mnasnet、shufflenetv2驾驶危险行为识别模型对比开发测试》 《基…

目标检测——OverFeat算法解读

论文&#xff1a;OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks 作者&#xff1a;Pierre Sermanet, David Eigen, Xiang Zhang, Michael Mathieu, Rob Fergus, Yann LeCun 链接&#xff1a;https://arxiv.org/abs/1312.6229 文章…

【kubernetes】k3s集群搭建(正在更新……)

文章目录 一、k3s简介二、快速搭建1.控制平面2.镜像加速 Pod容器集1.创建和管理pod Deployment(部署)与ReplicaSet(副本集)滚动更新 Service命名空间YAML语法管理对象常用命令缩写YAML规范 声明式配置对象标签选择器 容器运行时接口(CRI)与镜像导入导出容器运行时接口(CRI) 金丝…

C语言期末考试复习PTA数据类型及表达式-分支结构程序-循环结构-数组经典选择题

目录 第一章&#xff1a;C语言数据类型和表达式 第一题&#xff1a; 第二题&#xff1a; 第三题&#xff1a; 第四题&#xff1a; 第五题&#xff1a; 第六题&#xff1a; 第七题&#xff1a; 第八题&#xff1a; 第九题&#xff1a; 第二章&#xff1a;分支结构程序…

2023.12.7 关于 MySQL 事务详解

目录 事务的四大特性 原子性 一致性 持久性 隔离性 事务并发执行 脏读 不可重复读 幻读 四个隔离级别 read uncommitted read committed repeatable read serializable 事务的四大特性 原子性 一个事务中的所有操作&#xff0c;要么全部完成&#xff0c;要么全部…

一篇文章带你快速入门 Nuxt.js 服务端渲染

1. Nuxt.js 概述 1.1 我们一起做过的SPA SPA&#xff08;single page web application&#xff09;单页 Web 应用&#xff0c;Web 不再是一张张页面&#xff0c;而是一个整体的应用&#xff0c;一个由路由系统、数据系统、页面&#xff08;组件&#xff09;系统等等&#xff0…

16mic圆形麦克风阵列电路与声源定位算法设计

16mic圆形麦克风阵列电路与声源定位算法设计 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)&#xff1f;可加我微信hezkz17, 本群提供音频技术答疑服务&#xff0c;群赠送语音信号处理降噪算法&#xff0c;蓝牙耳机音频&#xff0c;DSP音频项目核心开发资料, 1 实…

多线程并发Ping脚本

1. 前言 最近需要ping地址&#xff0c;还是挺多的&#xff0c;就使用python搞一个ping脚本&#xff0c;记录一下&#xff0c;以免丢失了。 2. 脚本介绍 首先检查是否存在True.txt或False.txt文件&#xff0c;并在用户确认后进行删除&#xff0c;然后从IP.txt的文件中读取IP地…

灵活性与可靠性:SaaS云开发与定制开发小程序的优缺点解析

随着移动互联网的快速发展&#xff0c;微信小程序作为一种轻量级的应用程序&#xff0c;逐渐成为了企业开展业务和提升用户体验的重要工具。对于企业而言&#xff0c;选择通过SaaS云开发或定制开发的方式开发小程序&#xff0c;都是为了更好地实现业务目标。在这篇文章中&#…

【数据结构】插入排序,希尔排序,选择排序,堆排序,冒泡排序

1.插入排序 思路&#xff1a;插入排序将一个数插入一个有序的数组里面&#xff0c;将这个数和数组元素挨着比较&#xff0c;直到他插入到合适的位置。 动画演示&#xff1a; 步骤&#xff1a;1.定义一个变量tmp保存要插入的数据 2.在循环中用tmp和有序数组中的元素比较&#…

Spring全面详解

目录 1. Spring 概述 1.1 Spring是什么 1.2 Spring的作用 1.3 Spring IoC是什么 2. Spring 快速入门 3. Spring Bean 3.1 的实例化方式 空参构造器 3.2 的属性注入 全参构造器注入 setter方法注入 策略模式 3.3 注解管理 3.4 注解方式的属性注入 1. Spring 概述 …

聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化

聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化 目录 聚类分析 | Matlab实现基于谱聚类(Spectral Cluster)的数据聚类可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于谱聚类(Spectral Cluster)的聚类算法可视化&#xff08;完…

计算机毕业设计 基于SpringBoot的高校毕业与学位资格审核系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

Facebook自动回复脚本编写教程

在数字时代&#xff0c;社交媒体已经成为人们交流和建立联系的重要渠道&#xff0c;Facebook作为全球最大的社交媒体平台之一&#xff0c;拥有数十亿的用户&#xff0c;为企业和个人提供了无限的社交可能性。 然而&#xff0c;对于企业和个人来说&#xff0c;在Facebook上保持…

整合消息队列RabbitMQ

为什么使用消息队列MQ&#xff1f; 因为使用消息队列有多个好处&#xff1a;可以实现系统服务的解耦、异步和削峰&#xff1a; 异步通信&#xff1a;消息队列提供了一种异步通信的方式&#xff0c;发送方可以将消息发送到队列中&#xff0c;然后继续执行其他任务&#xff0c;…