当前位置: 首页 > news >正文

代码随想录算法训练营第四十八/九天 | 图 | 深度搜索 | 广度搜索

Day 48 49 总结

  • 自己实现中遇到哪些困难
  • 今日收获,记录一下自己的学习时间
    • 11:40 - 14:30
    • 12:30 - 13:30, 14:45 - 17:10

图论

  • 深度收缩 & 广度搜索
  • 并查集
  • 最小生成树
  • 拓扑排序
  • 最短路径算法

图论基础

    • 二维空间里,多个点之间相互连接
  • 图的种类
    • 有向图
    • 无向图
    • 加权
  • 度 Degree
    • 连接某个节点的边的数量
    • 出度,入度
  • 连通性
    • 节点联通情况
    • 连通图
      • 任意两个节点存在一条路径
    • 强连通图
      • 任务两个节点可以相互到达
    • 连通分量
      • 独立的连通子图(无向图中的极大连通子图)
    • 强连通分量
      • 有向图中极大强连通子图称之为该图的强连通分量
  • 图的构造
    • 邻接表
      • 数组 + 链表
      • 适用于稀疏图, 空间利用率高
    • 邻接矩阵
      • 二维数组
      • 表达简单,检查连接的速度块,适合稠密图
  • 图的遍历方式
    • 深度优先 dfs
    • 广度优先 bfs

深度优先搜索

  • 基本理解
    • 搜索方向,路径撤销(回溯)
  • 代码框架
  • void dfs(参数) {if (终止条件) {存放结果;return;}for (选择:本节点所连接的其他节点) {处理节点;dfs(图,选择的节点); // 递归回溯,撤销处理结果}
    }

98. 所有可达路径

题目连接:98. 所有可达路径

题目描述:

给定一个有 n 个节点的有向无环图,节点编号从 1 到 n。请编写一个函数,找出并返回所有从节点 1 到节点 n 的路径。每条路径应以节点编号的列表形式表示。

输入:

N个节点,M个边

s节点 与 t节点 是相连的

输出:

所有从1出发的路径  找出并返回所有从节点 1 到节点 n 的路径

实现思路:

用 N*N 的邻接表保存节点的连接信息,通过dfs收集所有路径。

使用visted变量记录当前访问过哪些节点,用于撤销操作 有向无环,不需要visted记录

使用for循环遍历邻接表中当前节点的行,搜索所有相邻节点

path变量保存临时搜索路径,result变量收集所有路径

代码实现:
public class Main {public static List<Integer> path = new ArrayList<>();public static List<List<Integer>> result = new ArrayList<>();public static int[][] graph;public static void main (String[] args) {/* code */Scanner in = new Scanner(System.in);String[] firstLine = in.nextLine().split(" ");int N = Integer.valueOf(firstLine[0]);int M = Integer.valueOf(firstLine[1]);graph = new int[N+1][N+1];visited = new boolean[N+1];for (int i=0; i<M; i++) {String[] line = in.nextLine().split(" ");int row = Integer.valueOf(line[0]);int col = Integer.valueOf(line[1]);graph[row][col] = 1;}        path.add(1);dfs1(1, N);if (result.size() == 0) System.out.println(-1);else {for (List<Integer> p : result) {for (int i=0; i<p.size()-1; i++)System.out.print(p.get(i) + " ");System.out.println(p.get(p.size()-1));}            }}public static void dfs1 (int node, int N) {// 到达路径末尾,收集路径if (node == N) { // 找到从1到N的路径result.add(new ArrayList<>(path));return;}for (int i=1; i<=N; i++) {if (graph[node][i] == 0) continue;path.add(i);dfs1(i, N);path.remove(path.size()-1);}            }}

 99. 岛屿数量

题目连接:99. 岛屿数量

题目描述:

给定一个由 1(陆地)和 0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。

输入:

N行,M列的矩阵

矩阵的具体数字,1代表一个岛,0代表水。

输出:

输出一个整数,表示岛屿的数量。如果不存在岛屿,则输出 0。

实现思路:

使用一个visted矩阵,标记都有哪些岛屿是访问过的。

按序访问每一个未访问过的岛屿,以该岛屿为起始点,进行深度搜索, 本次dfs结束之后,孤岛数量+1

深度搜索:

确定四个方向,上,右,下,左

分别dfs这四个分支

代码实现:
public class Main {public static void main (String[] args) {/* code */Scanner in = new Scanner(System.in);String[] firstLine = in.nextLine().split(" ");int N = Integer.valueOf(firstLine[0]);int M = Integer.valueOf(firstLine[1]);int[][] graph = new int[N][M];boolean[][] visited = new boolean[N][M];for (int i=0; i<N; i++) {for (int j=0; j<M; j++) {graph[i][j] = in.nextInt();   }}        // for (int i=0; i<N; i++) {//     System.out.println(Arrays.toString(graph[i]));// }int ct = 0;for (int i=0; i<N; i++) {for (int j=0; j<M; j++) {if (graph[i][j] == 1 && !visited[i][j]) {// System.out.println("start:" + i + " " + j);dfs(graph, visited,i,j, N, M);ct++;}}}System.out.println(ct);}public static void dfs(int[][] graph, boolean[][] visited, int x, int y, int N, int M) {int[] directions = {-1,0, 0,1, 1,0, 0,-1}; // 上右下左visited[x][y] = true;for (int i=0; i<4; i++) {int directX = directions[i*2];int directY = directions[i*2+1];if (directX+x >= 0 && directX+x < N && directY+y >= 0 && directY+y < M &&graph[directX+x][directY+y]==1 && !visited[directX+x][directY+y]) {// System.out.println("dfs:" + (directX+x) + " " + (directY+y));dfs(graph, visited, directX+x, directY+y, N, M);}}}}

广度优先搜索

  • BFS, 求点与点之间最短路径,以起始点为圆心,按圈搜索
  • 搜索过程
    • 起始点,起始点的四个方向
    • 队列保存顺(逆)时针的邻居
    • int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 表示四个方向
      // grid 是地图,也就是一个二维数组
      // visited标记访问过的节点,不要重复访问
      // x,y 表示开始搜索节点的下标
      void bfs(vector<vector<char>>& grid, vector<vector<bool>>& visited, int x, int y) {queue<pair<int, int>> que; // 定义队列que.push({x, y}); // 起始节点加入队列visited[x][y] = true; // 只要加入队列,立刻标记为访问过的节点while(!que.empty()) { // 开始遍历队列里的元素pair<int ,int> cur = que.front(); que.pop(); // 从队列取元素int curx = cur.first;int cury = cur.second; // 当前节点坐标for (int i = 0; i < 4; i++) { // 开始想当前节点的四个方向左右上下去遍历int nextx = curx + dir[i][0];int nexty = cury + dir[i][1]; // 获取周边四个方向的坐标if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;  // 坐标越界了,直接跳过if (!visited[nextx][nexty]) { // 如果节点没被访问过que.push({nextx, nexty});  // 队列添加该节点为下一轮要遍历的节点visited[nextx][nexty] = true; // 只要加入队列立刻标记,避免重复访问}}}}

99. 岛屿数量

题目连接:99. 岛屿数量

题目描述:

给定一个由 1(陆地)和 0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。

输入:

N行,M列的矩阵

矩阵的具体数字,1代表一个岛,0代表水。

输出:

输出一个整数,表示岛屿的数量。如果不存在岛屿,则输出 0。

实现思路:

使用一个visted矩阵,标记都有哪些岛屿是访问过的。

按序访问每一个未访问过的岛屿,以该岛屿为起始点,进行广度搜索, 本次bfs结束之后,孤岛数量+1

广度搜索:

确定四个方向,上,右,下,左

使用一个队列将这个四个岛屿存储起来,然后bfs

代码实现:
public class Main {public static void main (String[] args) {/* code */Scanner in = new Scanner(System.in);String[] firstLine = in.nextLine().split(" ");int N = Integer.valueOf(firstLine[0]);int M = Integer.valueOf(firstLine[1]);int[][] graph = new int[N][M];boolean[][] visited = new boolean[N][M];for (int i=0; i<N; i++) {for (int j=0; j<M; j++) {graph[i][j] = in.nextInt();   }}        int ct = 0;for (int i=0; i<N; i++) {for (int j=0; j<M; j++) {if (graph[i][j] == 1 && !visited[i][j]) {// System.out.println("start:" + i + " " + j);bfs(graph, visited,i,j, N, M);ct++;}}}System.out.println(ct);}public static void bfs(int[][] graph, boolean[][] visited, int X, int Y, int N, int M) {int[] directions = {-1,0, 0,1, 1,0, 0,-1}; // 上右下左Deque<int[]> queue = new LinkedList<>();queue.add(new int[]{X, Y});visited[X][Y] = true;while (!queue.isEmpty()) {int[] land = queue.poll();int x = land[0];int y = land[1];for (int i=0; i<4; i++) {int directX = directions[i*2];int directY = directions[i*2+1];if (directX+x >= 0 && directX+x < N && directY+y >= 0 && directY+y < M &&graph[directX+x][directY+y]==1 && !visited[directX+x][directY+y]) {queue.add(new int[]{directX+x,directY+y});visited[directX+x][directY+y] = true;}}}}}

100. 岛屿的最大面积

题目连接:100. 岛屿的最大面积

题目描述:

给定一个由 1(陆地)和 0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。

输入:

N行,M列的矩阵

矩阵的具体数字,1代表一个岛,0代表水。

输出:

输出一个整数,表示岛屿的最大面积。如果不存在岛屿,则输出 0。

实现思路:

使用一个visted矩阵,标记都有哪些岛屿是访问过的。

按序访问每一个未访问过的岛屿,以该岛屿为起始点,进行广度搜索, 本次bfs结束之后,得到当前岛屿的面积,保存最大面积。

广度搜索:

确定四个方向,上,右,下,左

使用一个队列将这个四个岛屿存储起来,然后bfs

代码实现:
// bfs
public class Main {public static void main (String[] args) {/* code */Scanner in = new Scanner(System.in);String[] line0 = in.nextLine().split(" ");int N = Integer.valueOf(line0[0]);int M = Integer.valueOf(line0[1]);int[][] graph = new int[N][M];boolean[][] visited = new boolean[N][M];for (int i=0; i<N; i++) {for (int j=0; j<M; j++)graph[i][j] = in.nextInt();}int max = 0;for (int i=0; i<N; i++) {for (int j=0; j<M; j++)if (graph[i][j] == 1 && !visited[i][j])max = Math.max(bfs(graph, visited, i, j, N, M), max);}System.out.println(max);}public static int bfs(int[][] graph, boolean[][] visited, int X, int Y, int N, int M) {int[] directions = {-1,0,  0,1,  1,0, 0 ,-1};int area = 0;Deque<int[]> queue = new LinkedList<>();queue.add(new int[]{X,Y});visited[X][Y] = true;while (!queue.isEmpty()) {int[] loc = queue.poll();area++;for (int i=0; i<4; i++) {int x = loc[0] + directions[i*2];int y = loc[1] + directions[i*2+1];if (x >= 0 && x < N && y >= 0 && y < M &&graph[x][y] == 1 && !visited[x][y]) {queue.add(new int[] {x, y});visited[x][y] = true;                        }}}return area;}}// dfs
public class Main {public static void main (String[] args) {int max = 0;for (int i=0; i<N; i++) {for (int j=0; j<M; j++)if (graph[i][j] == 1 && !visited[i][j])max = Math.max(dfs(graph, visited, i, j, N, M), max);}System.out.println(max);}public static int dfs(int[][] graph, boolean[][] visited, int X, int Y, int N, int M) {int[] directions = {-1,0,  0,1,  1,0, 0 ,-1};int area = 1;visited[X][Y] = true;for (int i=0; i<4; i++) {int x = X + directions[i*2];int y = Y + directions[i*2+1];if (x >= 0 && x < N && y >= 0 && y < M &&graph[x][y] == 1 && !visited[x][y]) {area += dfs(graph, visited, x, y, N, M);}}return area;}

101. 孤岛的总面积

题目连接:100. 岛屿的最大面积

题目描述:

给定一个由 1(陆地)和 0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。

输入:

N行,M列的矩阵

矩阵的具体数字,1代表一个岛,0代表水。

输出:

现在你需要计算所有孤岛的总面积,岛屿面积的计算方式为组成岛屿的陆地的总数。

实现思路:

使用一个visted矩阵,标记都有哪些岛屿是访问过的。

按序访问每一个未访问过的岛屿,以该岛屿为起始点,进行广度搜索, 本次bfs结束之后,将访问这个孤岛上的所有地块,得到岛屿面积。判断该岛屿是否存在一个地块接触边缘,如果是孤岛就合并面积,不是的话放弃计算面积。

广度搜索:

确定四个方向,上,右,下,左

使用一个队列将这个四个岛屿存储起来,然后bfs,遇到边界的格子就标记一下这个岛

代码实现:

102. 沉没孤岛

题目连接:102. 沉没孤岛

题目描述:

给定一个由 1(陆地)和 0(水)组成的矩阵,你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而成,并且四周都是水域。你可以假设矩阵外均被水包围。

输入:

N行,M列的矩阵

矩阵的具体数字,1代表一个岛,0代表水。

输出:

输出将孤岛“沉没”之后的岛屿矩阵。 注意:每个元素后面都有一个空格

实现思路:

使用一个visted矩阵,标记都有哪些岛屿是访问过的。

按序访问每一个未访问过的岛屿,以该岛屿为起始点,进行广度搜索, 本次bfs结束之后,将访问这个孤岛上的所有地块,得到岛屿面积。判断该岛屿是否存在一个地块接触边缘,如果是孤岛就将该孤岛变成水域.

搜索过程可以简化, 只从四个边开始搜索, 将搜索到的岛屿标记成2, 然后重新打印新的地图.

广度搜索:

确定四个方向,上,右,下,左

使用一个队列将这个四个岛屿存储起来,然后bfs,遇到边界的格子就标记一下这个岛

代码实现:
public class Main {static boolean isIsolated;public static void main (String[] args) {/* code */Scanner in = new Scanner(System.in);String[] line0 = in.nextLine().split(" ");int N = Integer.valueOf(line0[0]);int M = Integer.valueOf(line0[1]);int[][] graph = new int[N][M];boolean[][] visited = new boolean[N][M];for (int i=0; i<N; i++) {for (int j=0; j<M; j++)graph[i][j] = in.nextInt();}for (int i=0; i<N; i++) {if (graph[i][0] == 1 && !visited[i][0])bfs(graph, visited, i, 0, N, M);if (graph[i][M-1] == 1 && !visited[i][M-1])bfs(graph, visited, i, M-1, N, M);}for (int j=0; j<M; j++) {if (graph[0][j] == 1 && !visited[0][j])bfs(graph, visited, 0, j, N, M);if (graph[N-1][j] == 1 && !visited[N-1][j])bfs(graph, visited, N-1, j, N, M);            }for (int i=0; i<N; i++) {for (int j=0; j<M; j++) {if (graph[i][j] == 2)System.out.print(1+" ");elseSystem.out.print(0+" ");}System.out.println();}}public static int bfs(int[][] graph, boolean[][] visited, int X, int Y, int N, int M) {int[] directions = {-1,0,  0,1,  1,0, 0 ,-1};Deque<int[]> queue = new LinkedList<>();queue.add(new int[]{X,Y});visited[X][Y] = true;while (!queue.isEmpty()) {int[] loc = queue.poll();graph[loc[0]][loc[1]] = 2;for (int i=0; i<4; i++) {int x = loc[0] + directions[i*2];int y = loc[1] + directions[i*2+1];if (x >= 0 && x < N && y >= 0 && y < M &&graph[x][y] == 1 && !visited[x][y]) {queue.add(new int[] {x, y});visited[x][y] = true;                        }}}return 0;}
}

103. 水流问题

题目连接:103. 水流问题

题目描述:

现有一个 N × M 的矩阵,每个单元格包含一个数值,这个数值代表该位置的相对高度。矩阵的左边界和上边界被认为是第一组边界,而矩阵的右边界和下边界被视为第二组边界。

矩阵模拟了一个地形,当雨水落在上面时,水会根据地形的倾斜向低处流动,但只能从较高或等高的地点流向较低或等高并且相邻(上下左右方向)的地点。我们的目标是确定那些单元格,从这些单元格出发的水可以达到第一组边界和第二组边界。

输入:

N行,M列的矩阵

矩阵的具体数字,代表当前格子的高度

输出:

输出所有满足条件的格子: 从该格子出发的水,可以流向上左并且可以流向上右.

实现思路:

遍历所有格子, 进行bfs, 在bfs的过程当中, 修改两个全局变量, 表示搜索路径是否到达过一二边界.

bfs完成之后, 检查结果, 如果两个边界都到达过, 就放入结果集合中.

输出结果集合当中的坐标.

代码实现:
public class Main {static boolean arrivedA;static boolean arrivedB;public static void main (String[] args) {/* code */Scanner in = new Scanner(System.in);String[] line0 = in.nextLine().split(" ");int N = Integer.valueOf(line0[0]);int M = Integer.valueOf(line0[1]);int[][] graph = new int[N][M];for (int i=0; i<N; i++) {for (int j=0; j<M; j++)graph[i][j] = in.nextInt();}List<int[]> result = new ArrayList<>();for (int i=0; i<N; i++) {for (int j=0; j<M; j++) {arrivedA = false;arrivedB = false;;bfs(graph, i, j, N, M);if (arrivedA && arrivedB)result.add(new int[]{i,j});}}// 打印结果集合for (int[] res : result) {System.out.println(res[0] + " " + res[1]);}}public static void bfs(int[][] graph, int X, int Y, int N, int M) {boolean[][] visited = new boolean[N][M];int[] directions = {-1,0,  0,1,  1,0, 0 ,-1};Deque<int[]> queue = new LinkedList<>();queue.add(new int[]{X,Y});visited[X][Y] = true;while (!queue.isEmpty()) {int[] loc = queue.poll();// 检查是否达到边界if (loc[0] == 0 || loc[1] == 0) arrivedA = true;if (loc[0] == N-1 || loc[1] == M-1) arrivedB = true;for (int i=0; i<4; i++) {int x = loc[0] + directions[i*2];int y = loc[1] + directions[i*2+1];if (x >= 0 && x < N && y >= 0 && y < M &&graph[x][y] <= graph[loc[0]][loc[1]] && !visited[x][y]) {queue.add(new int[] {x, y});visited[x][y] = true;                        }}}return ;}
}

104.建造最大岛屿

题目连接: 104. 建造最大岛屿

题目描述:

现有一个 N × M 的矩阵,每个单元格值为 1 或 0, 分别代表 陆地 和 水.

可以选择一块水, 变成陆地, 然后和其他陆地连接成更大的岛屿.

输入:

N行,M列的矩阵 + 矩阵的具体数字,代表当前格子的高度

输出:

填平一格水域可以得到的最大岛屿面积.

实现思路:

遍历所有水域, 使用bfs来遍历所有与该水域相邻的岛屿, 求出岛屿面积,  记录最大岛屿面积.

考虑到特殊情况, 不存在水域的时候, 还需要遍历陆地来得到最大现存岛屿.

代码实现:

就是单纯bfs然后记录最大值

优化版本就是, 使用岛屿面积做标记, 再遍历水, 计算可以得到的最大面积.

110. 字符串接龙

题目连接: 110. 字符串接龙

题目描述:

初始字符串 xxx, 结果字符串 yyy, 中间字符串 xyz.

所有中间字符串只能使用一次, 如果两个字符串只差一个字符的话, 可以完成转换.

请问最少需要几步, 可以将初字符串经过中间字符串集合的转换,变成结果字符串.

实现思路:

求最短路径, 使用 bfs. 节点为字符串, 如果两个字符串只差一位字符, 那么这两个字符串存在一条路径.

使用HashMap 存储邻接表. Key 为字符串, value为一个数组保存了所有与该字符串存在路径关系的字符串,

HashMap构成的visited变量记录哪些节点被访问过(要求节点只能访问一次)

代码实现:
import java.util.Scanner;
public class Main {public static void main (String[] args) {/* code */Scanner in = new Scanner(System.in);int N = Integer.valueOf(in.nextLine());String[] line0 = in.nextLine().split(" ");String startStr = line0[0];String endStr = line0[1];HashMap<String, List<String>> graph = new HashMap<>();HashMap<String, Boolean> visited = new HashMap<>();for (int i=0; i<N; i++) {String s = in.nextLine();List<String> neighbours = new LinkedList<>();for (String key : graph.keySet()) {if (hasConnection(s, key)) {neighbours.add(key);graph.get(key).add(s);}}graph.put(s, neighbours);visited.put(s, false);}// 接入初始字符List<String> neighbours = new LinkedList<>();for (String key : graph.keySet()) {if (hasConnection(startStr, key)) {neighbours.add(key);}}graph.put(startStr, neighbours);visited.put(startStr, false);// 接入结束字符for (String key : graph.keySet()) {if (hasConnection(endStr, key)) {graph.get(key).add(endStr);}}visited.put(endStr, false);System.out.println(graph);System.out.println(bfs(graph, visited, startStr, endStr));}public static int bfs(HashMap<String, List<String>> graph, HashMap<String, Boolean> visited, String startStr, String endStr) {Deque<String> queue = new LinkedList<>();queue.add(startStr);int steps = 0;while (!queue.isEmpty()) {int idx = queue.size();for (int i=0; i<idx; i++) {String s = queue.poll();if (s.equals(endStr)) return steps+1;for (String next : graph.get(s)) {if (visited.get(next) == true) continue;visited.put(next, true);queue.add(next);}}steps++;}return 0;}public static boolean hasConnection(String s1, String s2) {int diff = 0;for (int i=0; i<s1.length(); i++) {if (s1.charAt(i) != s2.charAt(i))diff++;}return diff == 1;}
}

105.有向图的完全可达性

题目连接: 105. 有向图的完全可达性

题目描述:

给定一个有向图,包含 N 个节点,节点编号分别为 1,2,...,N。现从 1 号节点开始,如果可以从 1 号节点的边可以到达任何节点,则输出 1,否则输出 -1。

实现思路:

邻接矩阵表示节点之间的连接性, 使用 BFS 遍历所有节点. Visted数组记录哪些节点被访问过. 如果从1号节点开始的 BFS 结束之后, 所有节点都被visit过了, 说明可以从1号节点到达所有节点,

正常BFS就行

代码实现:

为了避免超时,使用中途退出判断,不能使用stream计算

return Arrays.stream(visited).sum() == N ? 1 : -1;

public class Main {public static void main (String[] args) {/* code */Scanner in = new Scanner(System.in);String[] line0 = in.nextLine().split(" ");int N = Integer.valueOf(line0[0]);int M = Integer.valueOf(line0[1]);// 使用邻接表,而非邻接矩阵List<List<Integer>> graph = new ArrayList<>(N);for (int i=0; i<N; i++) {List<Integer> list = new LinkedList<>();graph.add(list);}for (int $=0; $<M; $++) {int i = in.nextInt()-1;int j = in.nextInt()-1;graph.get(i).add(j);}System.out.println(bfs(graph, N));}public static int bfs(List<List<Integer>> graph, int N) {Deque<Integer> queue = new LinkedList<>();int[] visited = new int[N];queue.add(0);visited[0] = 1;while (!queue.isEmpty()) {int node = queue.poll();List<Integer> arr = graph.get(node);for (int next : arr) {if (visited[next] == 0) {queue.add(next);visited[next] = 1;}}}return Arrays.stream(visited).sum() == N ? 1 : -1;}
}

相关文章:

代码随想录算法训练营第四十八/九天 | 图 | 深度搜索 | 广度搜索

Day 48 49 总结 自己实现中遇到哪些困难今日收获&#xff0c;记录一下自己的学习时间 11:40 - 14:3012:30 - 13:30, 14:45 - 17:10 图论 深度收缩 & 广度搜索 并查集 最小生成树 拓扑排序 最短路径算法 图论基础 图 二维空间里&#xff0c;多个点之间相互连接图的…...

JavaEE初阶——多线程(线程安全-锁)

复习上节内容&#xff08;部分-掌握程度不够的&#xff09; 加锁&#xff0c;解决线程安全问题。 synchronized关键字&#xff0c;对锁对象进行加锁。 锁对象&#xff0c;可以是随便一个Object对象&#xff08;或者其子类的对象&#xff09;&#xff0c;需要关注的是&#xff…...

搭建大语言模型

安装和配置Ollama 首先在官网上下载Ollama&#xff0c;同时支持window&#xff0c;linux&#xff0c;macos系统。 下载下来是一个压缩包&#xff0c;直接解压缩即可&#xff0c;然后点击安装程序开始安装。 linux下载 执行以下命令&#xff0c;即可自动下载安装&#xff0c…...

QT6 Socket通讯封装(TCP/UDP)

为大家分享一下最近封装的以太网socket通讯接口 效果演示 如图&#xff0c;界面还没优化&#xff0c;后续更新 废话不多说直接上教程 添加库 如果为qmake项目中&#xff0c;在.pro文件添加 QT network QT core gui QT networkgreaterThan(QT_MAJOR_VERS…...

Linux中 vim 常用命令大全详细讲解

文章目录 前言一、Vim 基本操作 &#x1f579;️1.1 打开或创建1.2 退出编辑1.3 模式切换 二、Vim 光标移动命令 ↕️2.1 基本移动2.2 行内移动2.3. 单词移动2.4. 页面移动2.5. 行跳转 三、Vim 文本编辑命令 &#x1f4cb;3.1 插入和删除3.2 复制、剪切与粘贴3.3 替换与修改 四…...

vs 调试

常用&#xff1a; 调试->窗口-> 断点 监视 自动窗口 局部变量 调用堆栈 内存 反汇编&#xff08;也可以右键&#xff0c;转到反汇编&#xff09; 寄存器 快捷键&#xff1a; F5:启用调试&#xff0c;经常用来跳到下一个断点处 F9创建断点和取消断点。断点的重要作用&…...

使用 Kubernetes 部署 Redis 主从及 Sentinel 高可用架构(未做共享存储版)

文章目录 使用 Kubernetes 部署 Redis 主从及 Sentinel 高可用架构Redis 主从架构部署 (1.yaml)Redis Sentinel 部署 (2.yaml)Sentinel 服务暴露 (3.yaml)部署步骤总结 使用 Kubernetes 部署 Redis 主从及 Sentinel 高可用架构 本文将详细介绍如何在 Kubernetes 中部署 Redis …...

PLC网关,plc远程通信 —— 跨越距离远程控制运维升级

在日新月异的工业4.0时代&#xff0c;智能化、网络化已成为制造业转型升级的关键词。其中&#xff0c;PLC&#xff08;可编程逻辑控制器&#xff09;作为工业自动化控制的核心设备&#xff0c;其远程通信技术的突破&#xff0c;正引领着一场前所未有的工业变革。今天&#xff0…...

MySQL的历史和地位

秋招之后&#xff0c;开始深入学习后端开发知识啦。把学到的东西分享给大家最开心啦。就从MySQL开始吧。 首先说一下MySQL的历史和地位。主要是看一下我们为什么要学习&#xff0c;而不是说让我们学什么我们就学什么。 地位 这张图是我从DB-Engines截取的2024年12月最新的数据…...

Day12 洛谷 1320+1152+1615

零基础洛谷刷题记录 Day01 2024.11.18 Day02 2024.11.25 Day03 2024.11.26 Day04 2024.11.28 Day05 2024.11.29 Day06 2024 12.02 Day07 2024.12.03 Day08 2024 12 05 Day09 2024.12.07 Day10 2024.12.09 Day11 2024.12.10 Day12 2024.12.14 文章目录 零基础洛谷刷题记录1320&…...

四十六:如何使用Wireshark解密TLS/SSL报文?

TLS/SSL是保护网络通信的重要协议&#xff0c;其加密机制可以有效地防止敏感信息被窃取。然而&#xff0c;在调试网络应用或分析安全问题时&#xff0c;解密TLS/SSL流量是不可避免的需求。本文将介绍如何使用Wireshark解密TLS/SSL报文。 前提条件 在解密TLS/SSL报文之前&…...

【网络安全设备系列】7、流量监控设备

0x00 定义: 网络流量控制是一种利用软件或硬件方式来实现对电脑网络流量的控制。它的最主要方法&#xff0c;是引入QoS的概念&#xff0c;从通过为不同类型的 网络数据包标记&#xff0c;从而决定数据包通行的优先次序。 0x01 类型: 流控技术分为两种&#xff1a; 一种是…...

SpringCloud无介绍快使用,sentinel注解@SentinelResource的基本使用(二十三)

TOC 问题背景 从零开始学springcloud微服务项目 注意事项&#xff1a; 约定 > 配置 > 编码IDEA版本2021.1这个项目&#xff0c;我分了很多篇章&#xff0c;每篇文章一个操作步骤&#xff0c;目的是显得更简单明了controller调service&#xff0c;service调dao默认安装ngi…...

vue3 父组件调用子组件 el-drawer 抽屉

之前 Vue3 只停留在理论&#xff0c;现在项目重构&#xff0c;刚好可以系统的实战一下&#xff0c;下面是封装了一个抽屉表单组件&#xff0c;直接在父组件中通过调用子组件的方法打开抽屉&#xff1a; 父组件&#xff1a; <template><div id"app"><…...

JVM运行时数据区内部结构

VM内部结构 对于jvm来说他的内部结构主要分成三个部分&#xff0c;分别是类加载阶段&#xff0c;运行时数据区&#xff0c;以及垃圾回收区域&#xff0c;类加载我们放到之后来总结&#xff0c;今天先复习一下类运行区域 首先这个区域主要是分成如下几个部分 下面举个例子来解释…...

luckysheet与superslide冲突解决

[现象]控制台报错、界面无法操作 $是jquery。查看源码&#xff0c;发现mousewheel方法来自插件mousewheel&#xff0c;luckysheet初始应该会将mousewheel挂载在jquery上。 在控制台打印jquery取dom及其方法&#xff0c;结果如下&#xff1a; 不存在mousewheel方法&#xff0c…...

ubuntu环境调用onnxruntime找不到GPU的问题

问题&#xff1a; python安装好onnxruntime无法调用gpu。 通过如下代码测试&#xff0c;均为False。 import onnxruntime as ort# 检查ONNX Runtime是否支持CUDA def is_onnxruntime_cuda_supported():return ort.get_device() GPU# 检查ONNX Runtime是否使用CUDA def is_onn…...

【iOS】《Effective Objective-C 2.0》阅读笔记(一)

文章目录 前言了解OC语言的起源在类的头文件中尽量少引入其他头文件多用字面量语法&#xff0c;少用与之等价的方法字面量数值字面量数组字面量字典 多用类型常量&#xff0c;少用#define预处理指令用枚举法表示状态、选项、状态码 总结 前言 最近开始阅读一些iOS开发的相关书籍…...

linux在没网的情况下如何校验时间 超详细拿来即用

一、没有校时服务器的话 1、手动修改 sudo date --set"2024-06-17 13:44:00"二、有校时服务器的话 1、手动校时 ntpdate 14.193.73.22、自动校时 写一个校时服务脚本 14.193.73.2 是校验时间服务器 #!/bin/sh while true dontpdate 14.193.73.2sleep 5;hwclock…...

springBoot项目框架创建后缺少iml文件

springBoot项目创建好之后缺少iml文件 解决方案&#xff1a; 按两下ctrl出现一下内容 在右上角project的下拉框中选中缺少文件的项目 输入 mvn idea:module 回车执行重构...

【OJ题解】最长回文子串

个人主页: 起名字真南的CSDN博客 个人专栏: 【数据结构初阶】 &#x1f4d8; 基础数据结构【C语言】 &#x1f4bb; C语言编程技巧【C】 &#x1f680; 进阶C【OJ题解】 &#x1f4dd; 题解精讲 目录 **题目链接****解题思路****1. 初步判断****2. 回文子串性质****3. 判断是…...

kubeadm安装K8s高可用集群之集群初始化及master/node节点加入calico网络插件安装

系列文章目录 1.kubeadm安装K8s高可用集群之基础环境配置 2.kubeadm安装K8s集群之高可用组件keepalivednginx及kubeadm部署 3.kubeadm安装K8s高可用集群之集群初始化及master/node节点加入集群calico网络插件安装 kubeadm安装K8s高可用集群之集群初始化及master/node节点加入ca…...

动态设置路由标题title;动态设置路由配置meta;独享的守卫beforeEnter

案例&#xff1a;同一个页面即使新增&#xff0c;又是编辑、详情页。导致路由配置里的title无法固定 通过路由的独享的守卫beforeEnter解决配置&#xff1b;同时beforeEnter一定程度上可以帮助处理vue3缓存问题 {path: "methodApplicationFormOperate",name: "M…...

探秘UI自动化测试工具Playwright工作原理

相关文章&#xff1a;playwright系列教程 Playwright简介 微软出品的强大工具 Playwright是由微软推出的一款开源自动化测试工具&#xff0c;专门为Web测试和自动化场景而设计。在现代Web开发的快节奏环境下&#xff0c;其凭借出色的性能和丰富的功能&#xff0c;成为众多开…...

111.【C语言】数据结构之二叉树的销毁函数

目录 1.知识回顾 2.分析 3.代码 后序遍历销毁(最简洁) 前序遍历销毁(不推荐) 中序遍历销毁(不推荐) 4.将函数嵌入main函数中执行 1.知识回顾 106.【C语言】数据结构之二叉树的三种递归遍历方式 2.分析 销毁二叉树需要按照一定的顺序去销毁,例如:先销毁根还是先销毁根…...

WPF xaml 文件详解

<div id"content_views" class"htmledit_views"><h2><a name"t0"></a>1.总述</h2> 创建好了WPF项目后&#xff0c;最重要的是对 App和MainWindow的理解&#xff0c;在一开始的时候&#xff0c;极容易就直接在Main…...

win10配置免密ssh登录远程的ubuntu

为了在终端ssh远程和使用VScode远程我的VM上的ubuntu不需要设置密码&#xff0c;需要在win10配置免密ssh登录远程的ubuntu。 在win10打开cmd&#xff0c;执行下面的代码生成密钥对&#xff08;会提示进行设置&#xff0c;按照默认的配置就行&#xff0c;一直回车&#xff09;&…...

Android命令行工具--apksigner

使用 Android SDK Build Tools 修订版 24.0.3 及更高版本中提供的 apksigner 工具为 APK 签名&#xff0c;并确保 APK 的签名将在该 APK 支持的所有版本 Android 平台上成功通过验证。 注意&#xff1a;如果在使用 apksigner 为 APK 签名后又对 APK 做了更改&#xff0c;则 APK…...

Linux高性能服务器编程 | 读书笔记 |9.定时器

9. 定时器 网络程序需要处理定时事件&#xff0c;如定期检测一个客户连接的活动状态。服务器程序通常管理着众多定时事件&#xff0c;有效地组织这些定时事件&#xff0c;使其在预期的时间被触发且不影响服务器的主要逻辑&#xff0c;对于服务器的性能有至关重要的影响。为此&…...

UE5制作伤害浮动数字

效果演示&#xff1a; 首先创建一个控件UI 添加画布和文本 文本设置样式 添加伤害浮动动画&#xff0c;根据自己喜好调整&#xff0c;我设置了缩放和不透明度 添加绑定 转到事件图表&#xff0c;事件构造设置动画 创建actor蓝图类 添加widget 获取位置 设置位移 创建一个被击中…...

双亲委派机制是Java类加载器的一种工作模式

双亲委派机制是Java类加载器的一种工作模式&#xff0c;确保了类加载的一致性和安全性。以下是对双亲委派机制的详细解析&#xff1a; 一、定义与工作原理 双亲委派机制&#xff08;Parent Delegation Model&#xff09;要求除了顶层的启动类加载器外&#xff0c;其余的类加载…...

AI智算-k8s部署大语言模型管理工具Ollama

文章目录 简介k8s部署OllamaOpen WebUI访问Open-WebUI 简介 Github&#xff1a;https://github.com/ollama/ollama 官网&#xff1a;https://ollama.com/ API&#xff1a;https://github.com/ollama/ollama/blob/main/docs/api.md Ollama 是一个基于 Go 语言开发的可以本地运…...

百度23届秋招研发岗A卷

百度23届秋招研发岗A卷 2024/12/16 1.下面关于 SparkSQL 中 Catalyst 优化器的说法正确的是&#xff08;ABC&#xff09; A.Catalyst 优化器利用高级编程语言功能&#xff08;例如 Scala 的模式匹配&#xff09;来构建可扩展的查询优化器 B.Catalyst 包含树和操作树的规则集…...

米哈游大数据面试题及参考答案

怎么判断两个链表是否相交?怎么优化? 判断两个链表是否相交可以采用多种方法。 一种方法是使用双指针。首先分别遍历两个链表,得到两个链表的长度。然后让长链表的指针先走两个链表长度差的步数。之后,同时移动两个链表的指针,每次比较两个指针是否指向相同的节点。如果指…...

Android14 AOSP 允许system分区和vendor分区应用进行AIDL通信

在Android14上&#xff0c;出于种种原因&#xff0c;system分区的应用无法和vendor分区的应用直接通过AIDL的方法进行通信&#xff0c;但是项目的某个功能又需要如此。 好在Binder底层其实是支持的&#xff0c;只是在上层进行了屏蔽。 修改 frameworks/native/libs/binder/Bp…...

llm chat场景下的数据同步

背景 正常的chat/im通常是有单点登录或者利用类似广播的机制做多设备间内容同步的。而且由于长连接的存在&#xff0c;数据同步&#xff08;想起来&#xff09;相对简单。而llm的chat在缺失这两个机制的情况下&#xff0c;没见到特别好的做到了数据同步的产品。 llm chat主要两…...

视频去重原理及 Demo 示例

视频去重是一个常见的需求&#xff0c;主要用于视频库或平台管理中&#xff0c;通过判断视频是否相同&#xff08;或相似&#xff09;来移除冗余内容。实现视频去重可以通过多种方法&#xff0c;具体选择取决于业务场景和性能要求。 1. 视频去重的原理 1.1 基本原理 视频去重…...

【GIS教程】使用GDAL-Python将tif转为COG并在ArcGIS Js前端加载-附完整代码

目录 一、数据格式 二、COG特点 三、使用GDAL生成COG格式的数据 四、使用ArcGIS Maps SDK for JavaScript加载COG格式数据 一、数据格式 COG&#xff08;Cloud optimized GeoTIFF&#xff09;是一种GeoTiff格式的数据。托管在 HTTP 文件服务器上&#xff0c;可以代替geose…...

【ETCD】【源码阅读】深入解析 EtcdServer.applySnapshot方法

今天我们来一步步分析ETCD中applySnapshot函数 一、函数完整代码 函数的完整代码如下&#xff1a; func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) {if raft.IsEmptySnap(apply.snapshot) {return}applySnapshotInProgress.Inc()lg : s.Logger()lg.In…...

C# 实现 10 位纯数字随机数

本文将介绍如何用 C# 实现一个生成 10 位纯数字随机数的功能。以下是完整的代码示例&#xff1a; using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace RandomTset {class Program{// 使用GUID作为种子来创建随机数生成器static…...

【热力学与工程流体力学】流体静力学实验,雷诺实验,沿程阻力实验,丘里流量计流量系数测定,局部阻力系数的测定,稳态平板法测定材料的导热系数λ

关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…...

黑盒白盒测试

任务1 黑盒测试之等价类划分法 【任务需求】 【问题】例&#xff1a;某报表处理系统要求用户输入处理报表的日期&#xff0c;日期限制在2003年1月至2008年12月&#xff0c;即系统只能对该段期间内的报表进行处理&#xff0c;如日期不在此范围内&#xff0c;则显示输入错误信息…...

D99【python 接口自动化学习】- pytest进阶之fixture用法

day99 pytest使用conftest管理fixture 学习日期&#xff1a;20241216 学习目标&#xff1a;pytest基础用法 -- pytest使用conftest管理fixture 学习笔记&#xff1a; fixture(scope"function") conftest.py为固定写法&#xff0c;不可修改名字&#xff0c;使用c…...

RFDiffusion 计算二面角函数解读

th_dih函数来自util.py包,get_dih函数来自kinematics.py包。th_dih函数计算输入向量定义的二面角的余弦值和正弦值,返回一个包含 (cos⁡(ϕ),sin⁡(ϕ)) 的张量。get_dih 函数计算的是传统意义上的二面角。 源代码: def th_dih_v(ab, bc, cd):def th_cross(a, b):a, b = t…...

卓易通:鸿蒙Next系统的蜜糖还是毒药?

哈喽&#xff0c;我是老刘 最近很多人都在问鸿蒙next系统新上线的卓易通和出境易两款应用。 老刘分析了一下这个软件的一些细节&#xff0c;觉得还是蛮有意思的&#xff0c;我觉得可以从使用体验、底层原理和对鸿蒙生态的影响这三个角度来分析一下。 使用体验 性能 看到了一些测…...

Android:展锐T760平台camera PDAF调试

一、平台PDAF流程 目前展锐平台主要支持Shield PD Sensor、Dual PD Sensor 1、Shield PD Sensor Type1相位差和信心度结果直接从Sensor输出,不经过平台算法库。 Type2Sensor端抽取PD信息, 放在一块buffer输出, PDAF算法库算出相位差和信心度。 Type3Sensor端直接输出将带有…...

泷羽Sec学习笔记-zmap搭建炮台

zmap搭建炮台 zmap扫描环境&#xff1a;kali-linux 先更新软件库 sudo apt update 下载zmap sudo apt install zmap 开始扫描(需要root权限) sudo zmap -p 80 -o raw_ips.txt 代码解析&#xff1a; sudo&#xff1a;以超级用户&#xff08;管理员&#xff09;权限运行…...

web遇到的安全漏洞

最近项目又在做安全漏扫&#xff0c;记录下遇到的常见的web安全问题 越权 漏洞介绍 攻击者可以在授权状态下&#xff0c;通过修改数据包的参数&#xff0c;操作超出现有权限操作的功能点。举例 修改密码时&#xff0c;可以通过修改名称参数&#xff0c;修改任意用户密码。 任…...

Starfish 因子开发管理平台快速上手:如何完成策略编写与回测

DolphinDB 开发的因子开发管理平台 Starfish 围绕量化投研的因子、策略开发阶段设计&#xff0c;为用户提供了一个从数据管理、因子研究到策略回测的完整解决方案。 因子平台的回测引擎提供了多个关键的事件函数&#xff0c;涵盖策略初始化、每日盘前和盘后回调、逐笔、快照和…...

Oracle 数据库中,UNION ALL创建视图的使用详解

目录 UNION ALL 的特点 UNION ALL 的作用 1. 合并结果集 2. 保留重复行 3. 提高性能 UNION ALL 的使用场景 1. 日志或数据拼接 2. 区分数据来源 3. 解决分区表查询 注意事项 在创建视图中的作用 场景 1&#xff1a;合并多个表的数据到视图 表结构 目标 SQL 实现…...