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

深度优先搜索算法

目录

4.1 二叉树的最大深度(简单):深度优先搜索

4.2 对称二叉树(简单):递归

4.3 岛屿数量(中等):深度优先搜索

4.4 岛屿的最大面积(中等):深度优先搜索

4.5 路径总和(简单):深度优先搜索

4.6 被围绕的区域(中等):深度优先搜索

4.7 路径总和Ⅱ(中等):深度优先搜索

4.8 树的子结构(中等):前序遍历 + 递归

4.9 合并二叉树(简单):深度优先搜索

4.10 二叉搜索树的最近公共祖先(中等):两次遍历

4.11 所有可能的路径(中等):深度优先搜索 + 递归

4.12 省份数量(中等):深度优先搜索

4.13 深度优先搜索的总结


4.1 二叉树的最大深度(简单):深度优先搜索

题目:给定一个二叉树 root ,返回其最大深度。二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

思想:对于树而言,可以使用递归的方式来计算根节点的左右子节点的最大深度,因此二叉树的最大深度应该等于:

  • 左右子节点最大深度 + 1


总结:元素对应的最小路径和与其相邻元素的最小路径和有关,因此可以采用动态规划,具体是:

  • 元素对应的最小路径和 = min(上方相邻元素对应的最小路径和,左方相邻元素对应的最小路径和) + 当前元素值

    • dp[i][j]表示从左上角出发到[i][j]的最小路径和:有:dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + grid[i][j]

  • 特殊情况:

    • 只有一个点:dp[0][0] = grid[0][0];第一个数的最小路径和为该数的值

    • 只有一行:i=0,dp[0][j] = dp[0][j-1] + grid[0][j]

    • 只有一列:j=0,dp[i][0] = dp[i-1][0] + grid[i][0]


代码

class Solution {public int maxDepth(TreeNode root) {//根节点为nullif(root == null){return 0;}//只有根节点if(root.left == null && root.right == null){return 1;}//根节点存在左右子树;则比较左右子树的最大深度,取其较大值 + 1int max_Depth = 0;//得到左子树的最大深度if(root.left != null){max_Depth = Math.max(maxDepth(root.left),max_Depth);}//得到右子树的最大深度if(root.right != null){max_Depth = Math.max(maxDepth(root.right),max_Depth);}
​return max_Depth + 1;
​}
}

4.2 对称二叉树(简单):递归

题目:给你一个二叉树的根节点 root , 检查它是否轴对称

思想:可以先实现一个递归函数,使用两个指针pq同步遍历树,两个指针开始时都指向根节点,随后p右移时,q左移;p左移时,q右移;检查当前指针值是否相等


总结:判断二叉树是否对称,只需看:

  • 根节点是否一致

    • 左右子树是否值相等且对称

    可将一个root作两个用,然后分别比较root的左右子树值是否都相等


代码

class Solution {public boolean isSymmetric(TreeNode root) {return check(root, root);}
​public boolean check(TreeNode p, TreeNode q) {//先判断是否为空if (p == null && q == null) {return true;}//比较根节点是否相等if (p == null || q == null) {return false;}//比较根节点值是否都相同;然后比较p的左子树与q的右子树是否相等,并比较p的右子树与q的左子树是否相等return p.val == q.val && check(p.left, q.right) && check(p.right, q.left);}
}

4.3 岛屿数量(中等):深度优先搜索

题目:给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。

思想:其实这是一个寻找连通块数量的问题,岛屿只能从1开始,然后寻找与它相连接(上下左右)的1的数量,每一次找寻完毕后就说明这个连通块是一个岛屿;然后将找过的连通块中的元素由1设置为0(同一个岛屿在下一次找寻时是不会在此搜索的)


总结:深度优先搜索会从当前值开始,沿着某个节点一直走下去,直到结束,然后进行其它方向的搜索,直到搜索完相邻节点,我们只需给出搜索的起点与搜索方法即可;

  • 注意边界条件:对于数组而言不能超出左右边界[0, maxLength];


代码

class Solution {public int numIslands(char[][] grid) {//grid为空直接返回0if(grid == null || grid.length == 0){return 0;}
​//找到grid的行与列,为DFS做准备     int row = grid.length;int column = grid[0].length;
​//设置常量记录连通块(岛屿)数量int num_Islands = 0;
​//进行DFS查找for(int i = 0; i < row; i++){for(int j = 0; j < column; j++){//岛屿的前提条件是值为1if(grid[i][j] == '1'){++num_Islands;dfs(grid, i, j);}}}return num_Islands;}
​private void dfs(char[][] grid, int i, int j){//如果i、j超过边界(两种情况,要么小于0,要么大于数组长度)、数组值为0,则直接返回if(i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == '0'){return;}
​//将搜索过的数组值设置为'0',下一次搜索就不会在搜索到grid[i][j] = '0';
​//进行深度优先搜索: 上下左右都搜索一遍dfs(grid, i - 1, j);dfs(grid, i + 1, j);dfs(grid, i, j - 1);dfs(grid, i, j + 1);}
}

4.4 岛屿的最大面积(中等):深度优先搜索

题目:给你一个大小为 m x n 的二进制矩阵 grid

岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

岛屿的面积是岛上值为 1 的单元格的数目。

计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0

思想:也是一个寻找连通块数量的问题,只不过找到每个连通块还需要计算寻找连通块走过的步数,为了不重复走同一个位置,将找过的连通块中的元素由1设置为0(同一个岛屿在下一次找寻时是不会在此搜索的)


总结:深度优先搜索会从当前值开始,沿着某个节点一直走下去,直到结束,然后进行其它方向的搜索,直到搜索完相邻节点,我们只需给出搜索的起点与搜索方法即可;

  • 注意边界条件:对于数组而言不能超出左右边界[0, maxLength];


代码

class Solution {public int maxAreaOfIsland(int[][] grid) {if(grid == null || grid.length == 0 || grid[0].length == 0){return 0;}int row = grid.length;int column = grid[0].length;int res = 0;for(int i = 0; i < row; i++){for(int j = 0; j < column; j++){res = Math.max(res, dfs(grid, i, j));}}return res;}
​private int dfs(int[][] grid, int curr_i, int curr_j){if(curr_i <0 || curr_j < 0 || curr_i >= grid.length || curr_j >= grid[0].length || grid[curr_i][curr_j] == 0){return 0;}grid[curr_i][curr_j] = 0;
​//为了方便求出DFS走过多少步,将上下左右操作需要+ - 的两写入矩阵int[] di = {0,0,1,-1};int[] dj = {1,-1,0,0}; 
​int res = 1;//一样进行遍历; 分上下左右的4次遍历即可for(int i = 0; i < 4; i++){int curr_i1 = curr_i + di[i];int curr_j1 = curr_j + dj[i];res += dfs(grid, curr_i1, curr_j1);}return res;}
}

4.5 路径总和(简单):深度优先搜索

题目:给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false

思想:按照深度优先搜索的思想,从根节点开始,一条路走到叶子节点,并计算路径和(可以换一种思路,一条路走下去,判断目标值 targetSum 和走过的节点之差,到达叶子节点时 targetSum == currNode.val ,sum减到最后的值等于该叶子节点的值,说明是一条符合路径)


总结:深度优先搜索,就是一条路走到黑,不行再从最近路径换一条继续走到黑

  • 本题的巧妙之处在于:targetSum - root.val;将原本的求和转换思考为求目标值与每次路径差


代码

class Solution {public boolean hasPathSum(TreeNode root, int targetSum) {//根节点为空直接返回falseif(root == null){return false;}
​//如果没有左右子树说明是根节点也是叶子节点;判断值是否相等即可if(root.left == null && root.right == null){return root.val == targetSum;}
​//如果存在左右子树,进行深度优先搜索;//注意:这条可行路径可能是左子树也可能是右子树;减到叶子节点时,如果该叶子节点值等于sum就说明是符合要求的路径return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);}
}

4.6 被围绕的区域(中等):深度优先搜索

题目:给你一个 m x n 的矩阵 board ,由若干字符 'X''O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O''X' 填充;

注意:任何边界上的 O 都不会被填充为 X;因此:所有的不被包围的 O 都直接或间接与边界上的 O 相连。我们可以利用这个性质判断 O 是否在边界上

思想:以每一个边界上的O为起点,标记与它直接或间接相连的字母O

  • 最后我们遍历这个矩阵,对于每一个字母:

    • 如果该字母被标记过,则该字母为没有被字母 X 包围的字母 O,我们将其还原为字母 O;

    • 如果该字母没有被标记过,则该字母为被字母 X 包围的字母 O,我们将其修改为字母 X。


总结:深度优先搜索,就是一条路走到黑,不行再从最近路径换一条继续走到黑

  • 本题的巧妙之处在于:targetSum - root.val;将原本的求和转换思考为求目标值与每次路径差


代码

class Solution {public void solve(char[][] board) {//如果数组为空、只有一个值则不进行区域填充if(board == null || board.length == 0 || board[0].length == 0){return;}
​//对 m * n 的左右边界进行DFS搜索for(int i = 0; i < board.length; i++){dfs(board, i, 0);dfs(board, i, board[0].length - 1);}//对 m * n 的上下边界进行DFS搜索(排除左右搜索过的节点)for(int j = 1; j < board[0].length - 1; j++){dfs(board, 0, j);dfs(board, board.length - 1, j);}
​//对所有节点判断,若被标记过'isO'的就是连着边界'O'的,无法被填充为'X';将其他节点均填充为'X'即可for(int i = 0; i < board.length; i++){for(int j = 0; j < board[0].length; j++){if(board[i][j] == 'A'){board[i][j] = 'O';}else{board[i][j] = 'X';}}}
​
​}
​private void dfs(char[][] board,int row, int column){//边界条件,且只对边界上的'O'进行DFS搜索if(row < 0 || row >= board.length || column < 0 || column >= board[0].length || board[row][column] != 'O'){return;}//对于dfs的这个'O'点做一个标记,设为'isO'board[row][column] = 'A';
​//进行上下左右dfs搜索dfs(board, row, column - 1);dfs(board, row, column + 1);dfs(board, row - 1, column);dfs(board, row + 1, column);}
}

4.7 路径总和Ⅱ(中等):深度优先搜索

题目:给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

叶子节点 是指没有子节点的节点。

思想:按照深度优先搜索的思想,从根节点开始,一条路走到叶子节点,并计算路径和(可以换一种思路,一条路走下去,判断目标值 targetSum 和走过的节点之差,到达叶子节点时 targetSum == currNode.val ,sum减到最后的值等于该叶子节点的值,说明是一条符合路径)


总结:深度优先搜索,就是一条路走到黑,不行再从最近路径换一条继续走到黑

  • 本题的巧妙之处在于:targetSum - root.val;将原本的求和转换思考为求目标值与每次路径差


代码

class Solution {public List<List<Integer>> pathSum(TreeNode root, int targetSum) {//创建一个存储结果的数组List<List<Integer>> res = new ArrayList<>();//创建一个双端队列,存储每次符合目标的路径//注意:之所以用双端队列,是因为比如一条路径走到叶子节点了,先加左节点不等于sum,此时可以在尾部删除添加的左节点,然后再在尾部加上右节点的值Deque<Integer> deque = new LinkedList<>();dfs(root, targetSum, res, deque);return res;}
​private void dfs(TreeNode root, int targetSum, List<List<Integer>> res, Deque<Integer> deque){if(root == null){return;}//将节点值加入双端队列deque.offerLast(root.val);//目标值减少targetSum -= root.val;
​//如果到了叶子节点且targetSum = 0;说明是符合条件的路径,将deque加入resif(root.left == null && root.right == null && targetSum == 0){res.add(new LinkedList<>(deque));}
​//搜索左子树与右子树节点dfs(root.left, targetSum, res, deque);dfs(root.right, targetSum, res, deque);
​//如果最后一个节点不符合要求,将最后一个节点删除deque.pollLast();
​}
}

4.8 树的子结构(中等):前序遍历 + 递归

题目:输入两棵二叉树AB,判断B是不是A的子结构。(约定空树不是任意一个树的子结构);B是A的子结构, 即 A中有出现和B相同的结构和节点值。

思想:一棵树B是另一棵树A的子树的前提是:

  • A不能为空

  • B为空则B一定是A的子树

  • B不为空,则存在三种可能:

  • BA从根节点下出发的子结构

    • 此时要判断BA的根节点值是否相同,不同就肯定不是

    • 如果BA的根节点值相同,则继续判断BA的左右子树是否相同

  • BA的左子树中的子结构

  • BA的右子树中的子结构


总结:本题的重点在于:递归判断B是否为A的根节点下出发的子结构,进而判断B 的左右子树节点是否为A的左右子树节点


代码

class Solution {public boolean isSubStructure(TreeNode A, TreeNode B) {//B是A的子节点(在同时不为空)三种情况:B是A的根节点出发的子结构、B是A左子树子结构、B是A右子树子结构return (A != null && B != null) &&(isSubRoot(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B));}
​private boolean isSubRoot(TreeNode A, TreeNode B){//B为空,则就是子结构if(B == null){return true;}
​//A为空或者A、B的根节点值不同,则返回falseif(A == null || A.val != B.val){return false;}
​//到这一步说明A、B的根节点值相同,则判断A、B的左右子节点是否相同//此时需要递归,因为A、B的左右子节点判断时,一样是在证明B的左右子节点是否是A的左右子节点出发的子结构(其实就是下面的情况:B是A的根节点出发的子结构);因此调用isSubRoot()即可return isSubRoot(A.left, B.left) && isSubRoot(A.right, B.right);}
}

4.9 合并二叉树(简单):深度优先搜索

题目:给你两棵二叉树: root1root2

想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。返回合并后的二叉树。注意: 合并过程必须从两个树的根节点开始。

思想:深度优先搜索合并;合并对应节点有三种情况:

  • 两个节点都为空:合并后对应节点位置为空

  • 只有一个节点为空:合并后对应节点位置是不为空节点的值

  • 两个节点都不为空:合并后对应节点位置为两个值相加


总结:广度优先搜索的步骤:

  • 从某个节点开始搜索,将该节点存入队列

  • 若队列不为空,进行循环,该节点出队

  • 根据路径访问该节点的相邻节点,加入队列中;直到所有节点被访问


代码

class Solution {//合并两棵树public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {//如果任意一棵树为空,直接返回另一棵树即可if(root1 == null){return root2;}if(root2 == null){return root1;}//创建一颗新树,根节点为根节点之和TreeNode newTree = new TreeNode(root1.val + root2.val);//合并两个树的左节点newTree.left = mergeTrees(root1.left,root2.left);
​//合并两个树的右节点newTree.right = mergeTrees(root1.right, root2.right);
​return newTree;}
}

4.10 二叉搜索树的最近公共祖先(中等):两次遍历

题目:给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先(和1.11题解可以一样,但是二叉搜索树具有特定性质,可以根据其性质进行求解)

  • 最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

思想:二叉搜索树的特点在于:有序;节点的左子树都比该节点小,节点的右子树都比该节点大;使用二次遍历法,对于节点p而言

  • 从根节点遍历:

  • 如果当前节点为p,则找到节点

  • 如果当前节点值大于p,则 p在当前节点的左子树

  • 如果当前节点值小于p,则p在当前节点的右子树

  • 寻找节点的同时,记录走过的节点,当找到pq的路径pathP[i]pathQ[i]后,pq路径上的最后一个相同点就是最近公共祖先;即pathP[i] = pathQ[i]时只要i最大即可


总结:首先需要读懂题意,然后才能入手解决这种较为复杂的问题,可以设置一个专门判断是否存在节点p、q的函数,从而根据两种情况递归的使用该函数,最终得到结果


代码:

class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {//拿到从根节点找到p或者q的路径List<TreeNode> pathP = getPath(root, p); List<TreeNode> pathQ = getPath(root, q);TreeNode ancestor = new TreeNode();//找到路径后,拿到两数组相等时的最大节点就是最近公共祖先for(int i = 0; i < pathP.size() && i < pathQ.size(); i++){if(pathP.get(i) == pathQ.get(i)){ancestor = pathP.get(i);}}return ancestor;}
​private List<TreeNode> getPath(TreeNode root, TreeNode p){//创建接收走过路径的数组List<TreeNode> res = new ArrayList<>();TreeNode node = root;
​//如果root值不等于p的值:根据p与root的左右节点的大小判断p在左子树还是右子树while(node.val != p.val){res.add(node);if(p.val < node.val){node = node.left;}else{node = node.right;}}//如果root值等于p的值,也要放进数组,表示从根节点找到了pres.add(node);return res;}
}

4.11 所有可能的路径(中等):深度优先搜索 + 递归

题目:给你一个有 n 个节点的 有向无环图(DAG),请你找出所有从节点 0 到节点 n-1 的路径并输出(不要求按特定顺序

graph[i] 是一个从节点 i 可以访问的所有节点的列表(即从节点 i 到节点 graph[i][j]存在一条有向边)。

思想:使用深度优先搜索求出可能路径,从0出发,使用栈记录路径上的点,每次遍历到n - 1就将栈中的记录加入答案中

  • 有向无环图说明不会遍历同一个点,因此无法判断是否遍历过


总结:首先需要读懂题意,然后才能入手解决这种较为复杂的问题,可以设置一个专门判断是否存在节点p、q的函数,从而根据两种情况递归的使用该函数,最终得到结果


代码:

class Solution {//设置一个二维集合用来记录所有路径List<List<Integer>> res = new ArrayList<>();//设置一个栈用来辅助深度优先搜索:栈的实现不再用stack而是用deque代替;栈的作用就是从一个节点的路径出发,如果一条路走到黑,可以方便的回到上一个节点继续向另一条路出发(因为栈是先入后出的,可以保证前面的路径正确,只是最后一条路走到了头);最后将走到头的栈的值存入二维集合中即可Deque<Integer> stack = new LinkedList<>();
​public List<List<Integer>> allPathsSourceTarget(int[][] graph) {//从节点0出发,因此栈中第一个元素是节点0stack.offerLast(0);//搜索:从节点0到节点n - 1的路径dfs(graph, 0, graph.length - 1);return res;}
​private void dfs(int[][] graph, int x, int n){//如果搜索到n - 1节点,则将其加入集合中(注意此时的n就是graph.length - 1即n - 1)if(x == n){res.add(new ArrayList<Integer>(stack));return;}
​//如果还没搜索到最后一个节点,则从节点0所在索引的所有值出发搜索for(int y : graph[x]){stack.offerLast(y);//从节点0索引的每一个值出发搜索路径即可dfs(graph, y, n);//每次搜索完毕后出栈stack.pollLast();}}
}

4.12 省份数量(中等):深度优先搜索

题目:n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。返回矩阵中 省份 的数量。

思想:其实就是求一个矩阵中的连通块数量,使用深度优先搜索:

  • 遍历所有城市,如果城市未被访问过,则从该城市开始深度优先搜索

  • 通过 isConnected 可以知道该城市与哪个城市相连

    • 相连城市就是一个连通分量,直到同一个连通分量的所有城市都被访问到,就能够得到一个省份;

  • 最终所有连通分量的总数就是省份总数


总结:广度优先搜索的步骤:

  • 从某个节点开始搜索,将该节点存入队列

  • 若队列不为空,进行循环,该节点出队

  • 根据路径访问该节点的相邻节点,加入队列中;直到所有节点被访问


代码

class Solution {public int findCircleNum(int[][] isConnected) {//城市数量int city = isConnected.length;//设置省份数量int province = 0;boolean[] isVisited = new boolean[city];//遍历所有城市,如果城市未被访问过,则进行深度优先搜索 for(int i = 0; i < city; i++){if(isVisited[i] == false){dfs(isConnected, city, i, isVisited);province++;}}return province;}
​//从当前节点对所有城市进行深度优先搜索,路径按照isConnected中给出,访问过后将状态修改为true(默认为false)private void dfs(int[][] isConnected, int city, int i, boolean[] isVisited){for(int j = 0; j < city; j++){if(isConnected[i][j] == 1 && isVisited[j] == false){isVisited[j] = true;//当前节点搜索后,从相邻节点继续搜索dfs(isConnected, city, j, isVisited);}}}
}

4.13 深度优先搜索的总结

  • 思想:深度优先搜索就是一条路走到黑,从某个节点出发,然后一直走到头,然后从上一个节点继续出发走到头,直到所有节点都搜索完毕;

  • 实现:实现深度优先搜索时,应注意三点:

    • 观察节点出发的路径如何实现,在数组中经常是上下左右的实现,比如

    •         //进行深度优先搜索: 上下左右都搜索一遍dfs(grid, i - 1, j);dfs(grid, i + 1, j);dfs(grid, i, j - 1);dfs(grid, i, j + 1);
      ​//或者利用循环for(int j = 0; j < city; j++){if(isConnected[i][j] == 1 && isVisited[j] == false){isVisited[j] = true;//当前节点搜索后,从相邻节点继续搜索dfs(isConnected, city, j, isVisited);}}
    • 节点访问过后的标记,通常是使用boolean[] flag标记即可,访问后设置为true

    • 访问过的节点路径的存储,特殊情况下要用到

相关文章:

深度优先搜索算法

目录 4.1 二叉树的最大深度&#xff08;简单&#xff09;&#xff1a;深度优先搜索 4.2 对称二叉树&#xff08;简单&#xff09;&#xff1a;递归 4.3 岛屿数量&#xff08;中等&#xff09;&#xff1a;深度优先搜索 4.4 岛屿的最大面积&#xff08;中等&#xff09;&…...

k8s ----POD控制器详解

目录 一&#xff1a;pod控制器 1、Pod控制器及其功用 2、pod控制器类型 3、Pod与控制器之间的关系 二&#xff1a;Deployment 三&#xff1a;SatefulSet 1、StatefulSet组成 2、为什么要有headless&#xff1f; 3、为什么要有volumeClaimTemplate&#xff1f; 4、实现…...

ReactNative进阶(三十四):ipa Archive 阶段报错error: Multiple commands produce问题修复及思考

文章目录 一、前言二、问题描述三、问题解决四、拓展阅读五、拓展阅读 一、前言 在应用RN开发跨平台APP阶段&#xff0c;从git中拉取项目&#xff0c;应用Jenkins进行组包时&#xff0c;发现最终生成的ipa安装包版本号始终与项目中设置的版本号不一致。 二、问题描述 经过仔…...

MySQL索引ES索引

MySQL MySQL索引的种类 按照索引列值的唯一性:索引可分为唯一索引和非唯一索引; 唯一索引:此索引的每一个索引值只对应唯一的数据记录,对于单列唯一性索引,这保证单列不包含重复的值。对于多列唯一性索引,保证多个值的组合不重复。主键索引是唯一索引的特定类型。该索引…...

webSocket 聊天室 node.js 版

全局安装vue脚手架 npm install vue/cli -g 创建 vue3 ts 脚手架 vue create vue3-chatroom 后端代码 src 同级目录下建 server: const express require(express); const app express(); const http require(http); const server http.createServer(app);const io req…...

iptables防火墙(SNAT与DNAT)

目录 1 SNAT 1.1 SNAT原理与应用 1.2 SNAT工作原理 1.3 SNAT转换前提条件 2 SNAT示例 ​编辑 2.1 网关服务器配置 2.1.1 网关服务器配置网卡 2.1.2 开启SNAT命令 2.2 内网服务器端配置 2.3 外网服务器端配置 2.4 网卡服务器端添加规则 2.5 SNAT 测试 3 DNAT 3.1 网卡…...

第 359 场 LeetCode 周赛题解

A 判别首字母缩略词 签到题… class Solution { public:bool isAcronym(vector<string> &words, string s) {string pf;for (auto &s: words)pf.push_back(s[0]);return pf s;} };B k-avoiding 数组的最小总和 贪心&#xff1a;从 1 1 1开始升序枚举&#xff0c…...

【开源项目】Stream-Query的入门使用和原理分析

前言 无意间发现了一个有趣的项目&#xff0c;Stream-Query。了解了一下其基本的功能&#xff0c;可以帮助开发者省去Mapper的编写。在开发中&#xff0c;我们会编写entity和mapper来完成业务代码&#xff0c;但是Stream-Query可以省去mapper&#xff0c;只写entity。 快速入…...

微信小程序picker组件的简单使用 单选

<picker mode"selector" range"{{classData}}" bindchange"bindClassChange" value"{{classIndex}}" range-key"className"><view class"picker">{{classData[classIndex].className || 请选择班级}}…...

python、numpy、pytorch中的浅拷贝和深拷贝

1、Python中的浅拷贝和深拷贝 import copya [1, 2, 3, 4, [11, 22, 33, [111, 222]]] b a c a.copy() d copy.deepcopy(a)print(before modify\r\n a\r\n, a, \r\n,b a\r\n, b, \r\n,c a.copy()\r\n, c, \r\n,d copy.deepcopy(a)\r\n, d, \r\n)before modify a [1, 2…...

EasyRecovery14数据恢复软件支持各类存储设备的数据恢复

EasyRecovery14数据恢复软件专业数据恢复软件支持电脑、相机、移动硬盘、U盘、SD卡、内存卡、光盘、本地电子邮件和 RAID 磁盘阵列等各类存储设备的数据恢复。 目前市面上有许多数据恢复软件&#xff0c;但褒贬不一&#xff0c;而且数据恢复软件又不是一款会被经常使用的软件&a…...

玩机搞机----面具模块的组成 制作模块

root面具相信很多玩家都不陌生。早期玩友大都使用第三方卡刷补丁来对系统进行各种修复和添加功能。目前面具补丁代替了这些操作。今天的帖子了解下面具各种模块的组成和几种普遍的代码组成。 Magisk中运行的每个单独的shell脚本都将在内部的BusyBox的shell中执行。对于与第三方…...

注册中心/配置管理 —— SpringCloud Consul

Consul 概述 Consul 是一个可以提供服务发现&#xff0c;健康检查&#xff0c;多数据中心&#xff0c;key/Value 存储的分布式服务框架&#xff0c;用于实现分布式系统的发现与配置。Cousul 使用 Go 语言实现&#xff0c;因此天然具有可移植性&#xff0c;安装包仅包含一个可执…...

Next.js 13 你需要了解的 8 件事

目录 React 服务器组件 &#xff08;RSC&#xff09;服务器组件默认开启在 Next.js 中客户端组件也在服务器上呈现&#xff01;组成客户端和服务器组件编译Next.js 13 渲染模式桶文件有点坏了库集成&#xff1a;WIP 仍在进行中Route groups 路由组总结 在本文中&#xff0c;我们…...

计数排序(Count Sort)算法详解

1. 算法简介 计数排序&#xff08;Count Sort&#xff09;是一种非比较排序算法&#xff0c;其核心思想是统计数组中每个元素出现的次数&#xff0c;然后根据统计结果将元素按照顺序放回原数组中。计数排序的时间复杂度为O(nk)&#xff0c;其中n是数组的长度&#xff0c;k是数…...

Linux驱动开发(Day3)

驱动点灯&#xff1a;...

使用Vscode调试shell脚本

在vcode中安装bash dug插件 在vcode中添加launch.json配置&#xff0c;默认就好 参考&#xff1a;http://www.rply.cn/news/73966.html 推荐插件&#xff1a; shellman(支持shell,智能提示) shellcheck(shell语法检查) shell-format(shell格式化)...

OpenAI Function calling

开篇 原文出处 最近 OpenAI 在 6 月 13 号发布了新 feature&#xff0c;主要针对模型进行了优化&#xff0c;提供了 function calling 的功能&#xff0c;该 feature 对于很多集成 OpenAI 的应用来说绝对是一个“神器”。 Prompt 的演进 如果初看 OpenAI 官网对function ca…...

【C语言】字符分类函数、字符转换函数、内存函数

前言 之前我们用两篇文章介绍了strlen、strcpy、stract、strcmp、strncpy、strncat、strncmp、strstr、strtok、streeror这些函数 第一篇文章strlen、strcpy、stract 第二篇文章strcmp、strncpy、strncat、strncmp 第三篇文章strstr、strtok、streeror 今天我们就来学习字…...

Deep Learning With Pytorch - 最基本的感知机、贯序模型/分类、拟合

文章目录 如何利用pytorch创建一个简单的网络模型&#xff1f;Step1. 感知机&#xff0c;多层感知机&#xff08;MLP&#xff09;的基本结构Step2. 超平面 ω T ⋅ x b 0 \omega^{T}xb0 ωT⋅xb0 or ω T ⋅ x b \omega^{T}xb ωT⋅xb感知机函数 Step3. 利用感知机进行决策…...

测试工具coverage的高阶使用

在文章Python之单元测试使用的一点心得中&#xff0c;笔者介绍了自己在使用Python测试工具coverge的一点心得&#xff0c;包括&#xff1a; 使用coverage模块计算代码测试覆盖率使用coverage api计算代码测试覆盖率coverage配置文件的使用coverage badge的生成 本文在此基础上…...

安卓监听端口接收消息

文章目录 其他文章监听端口接收消息 建立新线程完整代码 其他文章 下面是我的另一篇文章&#xff0c;是在电脑上发送数据&#xff0c;配合本篇文章&#xff0c;可以实现电脑与手机的局域网通讯。直接复制粘贴就能行&#xff0c;非常滴好用。 点击连接 另外&#xff0c;如果你不…...

「Node」下载安装配置node.js

以下是Node.js的下载、安装和配置的全面教程&#xff1a; 下载 Node.js 打开 Node.js 官方网站&#xff1a;Previous Releases在主页上&#xff0c;您会看到两个版本可供选择&#xff1a;LTS&#xff08;长期支持版本&#xff09;和最新版&#xff08;Current&#xff09;。如…...

NOIP2014普及组,提高组 比例简化 飞扬的小鸟 答案

比例简化 说明 在社交媒体上&#xff0c;经常会看到针对某一个观点同意与否的民意调查以及结果。例如&#xff0c;对某一观点表示支持的有1498 人&#xff0c;反对的有 902人&#xff0c;那么赞同与反对的比例可以简单的记为1498:902。 不过&#xff0c;如果把调查结果就以这种…...

【Java】使用Apache POI识别PPT中的图片和文字,以及对应的大小、坐标、颜色、字体等

本文介绍如何使用Apache POI识别PPT中的图片和文字&#xff0c;获取图片的数据、大小、尺寸、坐标&#xff0c;以及获取文字的字体、大小、颜色、坐标。 官方文档&#xff1a;https://poi.apache.org/components/slideshow/xslf-cookbook.html 官方文档和网上的资料介绍的很少…...

根据源码,模拟实现 RabbitMQ - 实现消息持久化,统一硬盘操作(3)

目录 一、实现消息持久化 1.1、消息的存储设定 1.1.1、存储方式 1.1.2、存储格式约定 1.1.3、queue_data.txt 文件内容 1.1.4、queue_stat.txt 文件内容 1.2、实现 MessageFileManager 类 1.2.1、设计目录结构和文件格式 1.2.2、实现消息的写入 1.2.3、实现消息的删除…...

找到所有数组中消失的数(C语言详解)

题目&#xff1a;找到所有数组中消失的数 题目详情&#xff1a; 给你一个含 n 个整数的数组 nums &#xff0c;其中 nums[i] 在区间 [1,n] 内。请你找出所以在 [1,n] 范围内但没有出现在 nums 中的数字&#xff0c;并以数组的形式返回结果。 示例1&#xff1a; 输入&#xf…...

计算机毕设项目之基于django+mysql的疫情实时监控大屏系统(前后全分离)

系统阐述的是一款新冠肺炎疫情实时监控系统的设计与实现&#xff0c;对于Python、B/S结构、MySql进行了较为深入的学习与应用。主要针对系统的设计&#xff0c;描述&#xff0c;实现和分析与测试方面来表明开发的过程。开发中使用了 django框架和MySql数据库技术搭建系统的整体…...

Unity UI内存泄漏优化

项目一运行&#xff0c;占用的内存越来越多&#xff0c;不会释放&#xff0c;导致GC越来越频繁&#xff0c;越来越慢&#xff0c;这些都是为什么呢&#xff0c;今天从UI方面谈起。 首先让我们来聊聊什么是内存泄漏呢&#xff1f; 一般来讲内存泄漏就是指我们的应用向内存申请…...

学习笔记:Opencv实现图像特征提取算法SIFT

2023.8.19 为了在暑假内实现深度学习的进阶学习&#xff0c;特意学习一下传统算法&#xff0c;分享学习心得&#xff0c;记录学习日常 SIFT的百科&#xff1a; SIFT Scale Invariant Feature Transform, 尺度不变特征转换 全网最详细SIFT算法原理实现_ssift算法_Tc.小浩的博客…...

【golang】接口类型(interface)使用和原理

接口类型的类型字面量与结构体类型的看起来有些相似&#xff0c;它们都用花括号包裹一些核心信息。只不过&#xff0c;结构体类型包裹的是它的字段声明&#xff0c;而接口类型包裹的是它的方法定义。 接口类型声明中的这些方法所代表的就是该接口的方法集合。一个接口的方法集…...

【Linux操作系统】Linux系统编程中的共享存储映射(mmap)

在Linux系统编程中&#xff0c;进程之间的通信是一项重要的任务。共享存储映射&#xff08;mmap&#xff09;是一种高效的进程通信方式&#xff0c;它允许多个进程共享同一个内存区域&#xff0c;从而实现数据的共享和通信。本文将介绍共享存储映射的概念、原理、使用方法和注意…...

2235.两整数相加:19种语言解法(力扣全解法)

【LetMeFly】2235.两整数相加&#xff1a;19种语言解法&#xff08;力扣全解法&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/add-two-integers/ 给你两个整数 num1 和 num2&#xff0c;返回这两个整数的和。 示例 1&#xff1a; 输入&#xff1a;num…...

中国剩余定理及扩展

目录 中国剩余定理解释 中国剩余定理扩展——求解模数不互质情况下的线性方程组&#xff1a; 代码实现&#xff1a; 互质&#xff1a; 非互质&#xff1a; 中国剩余定理解释 在《孙子算经》中有这样一个问题&#xff1a;“今有物不知其数&#xff0c;三三数之剩二&#x…...

数据在内存中的存储(deeper)

数据在内存中的存储&#xff08;deeper&#xff09; 一.数据类型的详细介绍二.整形在内存中的存储三.浮点型在内存中的存储 一.数据类型的详细介绍 类型的意义&#xff1a; 使用这个类型开辟内存空间的大小&#xff08;大小决定了使用范围&#xff09;如何看待内存空间的视角…...

算法修炼Day52|● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组

LeetCode:300.最长递增子序列 300. 最长递增子序列 - 力扣&#xff08;LeetCode&#xff09; 1.思路 dp[i]的状态表示以nums[i]为结尾的最长递增子序列的个数。 dp[i]有很多个&#xff0c;选择其中最大的dp[i]Math.max(dp[j]1,dp[i]) 2.代码实现 1class Solution {2 pub…...

使用 HTML、CSS 和 JavaScript 创建实时 Web 编辑器

使用 HTML、CSS 和 JavaScript 创建实时 Web 编辑器 在本文中&#xff0c;我们将创建一个实时网页编辑器。这是一个 Web 应用程序&#xff0c;允许我们在网页上编写 HTML、CSS 和 JavaScript 代码并实时查看结果。这是学习 Web 开发和测试代码片段的绝佳工具。我们将使用ifram…...

百望云联合华为发布票财税链一体化数智解决方案 赋能企业数字化升级

随着数据跃升为数字经济关键生产要素&#xff0c;数据安全成为整个数字化建设的重中之重。为更好地帮助企业发展&#xff0c;中央及全国和地方政府相继出台了多部与数据相关的政策法规&#xff0c;鼓励各领域服务商提供具有自主创新的软件产品与服务&#xff0c;帮助企业在合规…...

实现两个栈模拟队列

实现两个栈模拟队列 思路&#xff1a;可以想象一下左手和右手&#xff0c;两个栈&#xff1a;stack1&#xff08;数据所在的栈&#xff09; &#xff0c;stack2&#xff08;临时存放&#xff09;。 入队&#xff1a;需要将入队 num 加在 stack1 的栈顶即可&#xff1b; 出队&am…...

无涯教程-TensorFlow - 单词嵌入

Word embedding是从离散对象(如单词)映射到向量和实数的概念&#xff0c;可将离散的输入对象有效地转换为有用的向量。 Word embedding的输入如下所示: blue: (0.01359, 0.00075997, 0.24608, ..., -0.2524, 1.0048, 0.06259) blues: (0.01396, 0.11887, -0.48963, ..., 0.03…...

Facebook AI mBART:巴别塔的硅解

2018年&#xff0c;谷歌发布了BERT&#xff08;来自transformers的双向编码器表示&#xff09;&#xff0c;这是一种预训练的语言模型&#xff0c;在一系列自然语言处理&#xff08;NLP&#xff09;任务中对SOTA结果进行评分&#xff0c;并彻底改变了研究领域。类似的基于变压器…...

BDA初级分析——SQL清洗和整理数据

一、数据处理 数据处理之类型转换 字符格式与数值格式存储的数据&#xff0c;同样是进行大小排序&#xff0c; 会有什么区别&#xff1f; 以rev为例&#xff0c;看看字符格式与数值格式存储时&#xff0c;排序会有什么区别&#xff1f; 用cast as转换为字符后进行排序 SEL…...

汽车后视镜反射率测定仪

后视镜是驾驶员坐在驾驶室座位上直接获取汽车后方、侧方和下方等外部信息的工具。它起着“第三只眼睛”的作用。后视镜按安装位置划分通常分为车外后视镜、监视镜和内后视镜。外后视镜观察汽车后侧方监视镜观察汽车前下方内后视镜观察汽车后方及车内情况。用途不一样镜面结构也…...

Redis学习笔记

redis相关内容 默认端口6379 默认16个数据库&#xff0c;初始默认使用0号库 使用select 切换数据库 统一密码管理&#xff0c;所有库密码相同 dbsize&#xff1a;查看当前库key的数量 flushdb&#xff1a;清空当前库 flushall&#xff1a;清空全部库 redis是单线程 多路…...

韩顺平Linux 四十四--

四十四、rwx权限 权限的基本介绍 输入指令 ls -l 显示的内容如下 -rwxrw-r-- 1 root 1213 Feb 2 09:39 abc0-9位说明 第0位确定文件类型&#xff08;d , - , l , c , b) l 是链接&#xff0c;相当于 windows 的快捷方式- 代表是文件是普通文件d 是目录&#xff0c;相…...

【支付宝小程序】分包优化教程

&#x1f996;我是Sam9029&#xff0c;一个前端 Sam9029的CSDN博客主页:Sam9029的博客_CSDN博客-JS学习,CSS学习,Vue-2领域博主 &#x1f431;‍&#x1f409;&#x1f431;‍&#x1f409;恭喜你&#xff0c;若此文你认为写的不错&#xff0c;不要吝啬你的赞扬&#xff0c;求收…...

语言基础2 矩阵和数组

语言基础2 矩阵和数组 矩阵和数组是matlab中信息和数据的基本表示形式 可以创建常用的数组和网格 合并现有的数组 操作数组的形状和内容 以及使用索引访问数组元素 用到的函数列表如下 一 创建 串联和扩展矩阵 矩阵时按行和列排列的数据元素的二维数据元素的二维矩…...

springMVC中过滤器抛出异常,自定义异常捕获

在过滤器中引入org.springframework.web.servlet.HandlerExceptionResolver AutowiredQualifier("handlerExceptionResolver")private HandlerExceptionResolver resolver; // doFilter中处理if (条件1) {if (条件2) {resolver.resolveException(request, response, …...

图像检索技术研究:深度度量与深度散列在相似性学习中的应用比较与实践 - 使用Python与Jupyter环境

引言 在计算机视觉领域&#xff0c;图像检索是一个长期存在并持续受到研究者关注的重要话题。随着大数据时代的到来&#xff0c;如何高效、准确地从海量数据中检索到相似的图像成为一个巨大的挑战。传统的检索方法在大数据环境下表现不佳&#xff0c;而深度学习技术的崛起为图…...

CSS加载失败的6个原因

有很多刚刚接触 CSS 的新手有时会遇到 CSS 加载失败这个问题&#xff0c;但测试时&#xff0c;网页上没有显示该样式的问题&#xff0c;这就说明 CSS 加载失败了。出现这种状况一般是因为的 CSS 路径书写错&#xff0c;或者是在浏览器中禁止掉了 CSS 的加载&#xff0c;可以重新…...