[算法和数据结构]--回溯算法之DFS初识
回溯算法——DFS
- DFS介绍(Depth First Search)
- DFS经典题目
- 1. 员工的重要性
- 2. 图像渲染
- 3.被围绕的区域
- 4.岛屿数量
- 5. 电话号码的字母组合
- 6.数字组合
- 7. 活字印刷
- 8. N皇后
DFS介绍(Depth First Search)
- 回溯法(back tracking)(探索与回溯法)回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。
- 回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。也可以称为剪枝点,所谓的剪枝,指的是把不会找到目标,或者不必要的路径裁剪掉。
- DFS算法就是深度优先算法,在数据结构的学习中,二叉树的前序遍历就是属于深度优先算法。
深度优先搜索其实就是一条路走到黑。我们来看一道很经典的DFS题目让我们来了解深度优先搜索。
✨问题描述:
假如有编号为1~ 3的3张扑克牌和编号为1~3的3个盒子,现在需要将3张牌分别放到3个盒子中去,且每个盒子只能放
一张牌,一共有多少种不同的放法
✨ 思路分析:
上面这张图画出了回溯过程的前半部分,接下来按着深度优先搜索的方式接着进行回溯,我们可以得到剩下的三种情况:
我们进行上述的深度优先搜索的时候,我们在一个盒子中放扑克牌是从1 – 3号扑克牌依次进行放入的,这样我们可以用for循环搞定。但是我们如何确定该位置要放的扑克牌,是否在前面已经被放过了呢?我们可以使用一个标记数组 int[] book 来记录当前扑克牌在前面是否被放入了。
✨ 代码实现:
public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();//盒子和牌的个数int[] book = new int[n + 1];int[] box = new int[n + 1];Dfs(1,book,box,n);}private static void Dfs(int idx, int[] book, int[] box, int n) {if (idx == n + 1){//此时已经完成了一次深度优先搜索for (int i = 1; i <= n; i++) {System.out.print(box[i] + " ");}System.out.println();return;}for (int i = 1; i <= n; i++) {//深度优先搜索,去放置牌if(book[i] == 0){box[idx] = i;//idx个盒子放第i个牌book[i] = 1;//代表第i个牌已经使用了Dfs(idx + 1, book, box, n);//处理下一个盒子book[i] = 0;//第i张牌重新拿到手里}}}
DFS经典题目
1. 员工的重要性
原题链接
✨问题描述:
给定一个保存员工信息的数据结构,它包含了员工 唯一的 id ,重要度 和 直系下属的 id 。
比如,员工 1 是员工 2 的领导,员工 2 是员工 3 的领导。他们相应的重要度为 15 , 10 , 5 。那么员工 1 的数据结构是 [1, 15, [2]] ,员工 2的 数据结构是 [2, 10, [3]] ,员工 3 的数据结构是 [3, 5, []] 。注意虽然员工 3 也是员工 1 的一个下属,但是由于 并不是直系 下属,因此没有体现在员工 1 的数据结构中。
现在输入一个公司的所有员工信息,以及单个员工 id ,返回这个员工和他所有下属的重要度之和。
✨输入案例:
输入:[[1, 5, [2, 3]], [2, 3, []], [3, 3, []]], 1
输出:11
解释:
员工 1 自身的重要度是 5 ,他有两个直系下属 2 和 3 ,而且 2 和 3 的重要度均为 3 。因此员工 1 的总重要度是 5 + 3 + 3 = 11 。
✨题目分析
该问题就类似于二叉树的前序遍历。从单个员工的重要度开始计算,依次遍历员工的下属,下属有员工再次搜索下属。直到没有下属员工再依次回退查看有没有其他的子员工。
✨ 解题代码:
public int getImportance(List<Employee> employees, int id) {Map<Integer,Employee> empMap = new HashMap<>();//用哈希表存储数据查找会更方便更快速。for (Employee employee: employees) {empMap.put(employee.id,employee);}return DFS(empMap,id);}private int DFS(Map<Integer, Employee> empMap, int id) {int sum = empMap.get(id).importance;//加上该员工的重要度for (int curId:empMap.get(id).subordinates) {//该员工有下属就进行for-each循环DFS,没有的话就不进去循环sum += DFS(empMap,curId);}return sum;}
2. 图像渲染
原题链接
✨问题描述:
有一幅以 m x n 的二维整数数组表示的图画 image ,其中 image[i][j] 表示该图画的像素值大小。
你也被给予三个整数 sr , sc 和 newColor 。你应该从像素 image[sr][sc] 开始对图像进行 上色填充 。
为了完成 上色工作 ,从初始像素开始,记录初始坐标的 上下左右四个方向上 像素值与初始坐标相同的相连像素点,接着再记录这四个方向上符合条件的像素点与他们对应 四个方向上 像素值与初始坐标相同的相连像素点,……,重复该过程。将所有有记录的像素点的颜色值改为 newColor 。
最后返回 经过上色渲染后的图像 。
✨题目样例:
案例1:
输入: image = [[1,1,1],[1,1,0],[1,0,1]],sr = 1, sc = 1, newColor = 2
输出: [[2,2,2],[2,2,0],[2,0,1]]
解析: 在图像的正中间,(坐标(sr,sc)=(1,1)),在路径上所有符合条件的像素点的颜色都被更改成2。
注意,右下角的像素没有更改为2,因为它不是在上下左右四个方向上与初始点相连的像素点。
案例2:
输入: image = [[0,0,0],[0,0,0]], sr = 0, sc = 0, newColor = 2
输出: [[2,2,2],[2,2,2]]
✨ 题目分析:
这个题目用DFS算法来解决。把初始四围与其颜色相同的位置进行渲染,渲染了一个位置,就找其周围与其颜色相同的位置进行渲染。同时还需要判断四周的位置是否越界。如果渲染颜色和初始位置的颜色不同的话,我们渲染时候,仅仅需要判断是否为原始位置的颜色相同,渲染后的位置和未被渲染的位置能够清楚的区分,但是如果初始位置的颜色和渲染染色相同就会区分不了该位置是渲染过的,还是未被渲染的和初始位置原色相同的。为了解决这个问题,我们就引入一个标记数组 int[][] book 来标记该位置是否被渲染过了。
✨ 解题代码
int[][] nextP= {{1,0},{-1,0},{0,-1},{0,1}};//偏移数组,通过原位置找到相邻的四个位置public int[][] floodFill(int[][] image, int sr, int sc, int color) {int oldColor = image[sr][sc];//记录要修改坐标的旧颜色int row = image.length;int col = image[0].length;int[][] book = new int[row][col];//创建一个标记数组DFS(image,book,sr,sc,oldColor,color,row,col);//深度优先搜索寻找是否有相同颜色的位置return image;}private void DFS(int[][] image, int[][] book, int sr, int sc, int oldColor, int color,int row,int col) {image[sr][sc] = color;//修改当前位置的颜色book[sr][sc] = 1;//标记当前位置已经被修改过了for (int i = 0; i < 4; i++) {//搜索上下左右四个位置的颜色是否符合原颜色int newX = sr + nextP[i][0];int newY = sc + nextP[i][1];if (newX < 0 || newX >= row|| newY < 0 || newY >= col) {//判断新坐标是否越界continue;}//判断当前位置是否需要进行图像渲染if (image[newX][newY] == oldColor && book[newX][newY] == 0){//新的位置的处理DFS(image,book,newX,newY,oldColor,color,row,col);}}}
3.被围绕的区域
原题链接
✨问题描述:
给你一个 m x n 的矩阵 board ,由若干字符 ‘X’ 和 ‘O’ ,找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。
✨题目案例:
案例1: 输入:board =
[[“X”,“X”,“X”,“X”],[“X”,“O”,“O”,“X”],[“X”,“X”,“O”,“X”],[“X”,“O”,“X”,“X”]]
输出:[[“X”,“X”,“X”,“X”],[“X”,“X”,“X”,“X”],[“X”,“X”,“X”,“X”],[“X”,“O”,“X”,“X”]]
解释:被围绕的区间不会存在于边界上,换句话说,任何边界上的 ‘O’ 都不会被填充为 ‘X’。 任何不在边界上,或不与边界上的 ‘O’ 相连的
‘O’ 最终都会被填充为 ‘X’。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
案例2:
输入:board = [[“X”]]
输出:[[“X”]]
✨ 题目分析:
把整个区域扩大一下,变成上图这种。上图中红圈里的就是被包围的区域,被包围的区域比较不容易找到,但是未被包围的区域,就比较容易的找到了。我们可以用深度优先搜索的方式进行找到没有被包围的区域,间接找到被包围的区域。
✨ 解题代码
int[][] nextP = {{1,0},{-1,0},{0,1},{0,-1}};//方向数组,下一步从哪个方向搜索 下 上 右 左public void solve(char[][] board) {int row = board.length;int col = board[0].length;//用逆向思维的方式求未被包围的区域,间接求出被包围的区域for (int i = 0; i < row; i++) {//寻找左列边界的区域中‘O’的位置if (board[i][0] == 'O'){DFS(board,i,0,row,col);}if (board[i][col - 1] == 'O'){//寻找右列边界的区域中‘O’的位置DFS(board,i,col - 1,row,col);}}for (int j = 0; j < col; j++) {if (board[0][j] == 'O'){//判断上边界是否有‘O’DFS(board,0,j,row,col);}if (board[row - 1][j] == 'O'){//判断下边界是否有‘O’DFS(board,row - 1,j,row,col);}}for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {if (board[i][j] == 'O'){board[i][j] = 'X';}if (board[i][j] == '*'){board[i][j] = 'O';}}}}private void DFS(char[][] board, int x, int y, int row, int col) {board[x][y] = '*';//代表该‘O’已经被搜索过了for (int i = 0; i < 4; i++) {int newX = x + nextP[i][0];int newY = y + nextP[i][1];if (newX < 0 || newX >= row||newY < 0 || newY >= col){//判断探索位置是否越界continue;}if (board[newX][newY] == 'O'){//判断该位置是否需要进行探索DFS(board,newX,newY,row,col);}}}
4.岛屿数量
原题链接
✨ 题目描述:
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
✨ 题目案例:
案例1:
输入:grid = [
[“1”,“1”,“1”,“1”,“0”],
[“1”,“1”,“0”,“1”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“0”,“0”,“0”]
]
输出:1
案例2:
输入:grid = [
[“1”,“1”,“0”,“0”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“1”,“0”,“0”],
[“0”,“0”,“0”,“1”,“1”]
]
输出:3
✨ 题目分析:
这个问题和第二题的思路有很多类似的地方。都是进行一个深度优先搜索,但是第二题给出了搜索的起始位置。这个题目搜索的起始位置我们可以对整个数组进行遍历。我们可以对搜索过的陆地位置进行标记,因为此问题我们仅仅只有‘0’和‘1’两种情况,我们可以对grid数组本身进行进行字符的改变来表示他是一个已经被搜索过的陆地了,这个字符我们可以换成一个不同于‘0’和‘1’的,比如‘*’;
✨ 解题代码:
int[][] nextP = {{1,0},{-1,0},{0,1},{0,-1}};//方向数组,下一步从哪个方向搜索 下 上 右 左public int numIslands(char[][] grid) {int row = grid.length;int col = grid[0].length;int count = 0;for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {if (grid[i][j] == '1'){DFS(grid,i,j,row,col);count++;}}}return count;}private void DFS(char[][] grid,int posX, int poxY ,int row, int col) {grid[posX][poxY] = '*';//对已经搜索过的陆地进行标记,以防重复搜索造成死递归。for (int i = 0; i < 4; i++) {int newX = posX + nextP[i][0];int newY = poxY + nextP[i][1];if (newX < 0 || newX >= row|| newY < 0 || newY >= col) {//判断是否是越界了continue;}if (grid[newX][newY] == '1'){//是未被搜索的陆地,就进行下一步搜索DFS(grid, newX, newY, row, col);}}}
5. 电话号码的字母组合
原题链接
✨ 题目描述:
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
✨ 题目案例:
案例1:
输入:digits = “23”
输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]
案例2:
输入:digits = “”
输出:[]
案例3:
输入:digits = “2”
输出:[“a”,“b”,“c”]
✨ 题目分析:
结合案例可以看出,这个问题得到的字母组合和digits字符串的长度相同。当digits长度为0的时候,得到的结果是没有任何元素的一个集合。我们可以建立一个联系,用电话按键数字对应字符串在深度优先搜索的时候用于查找我们数字对应的字符串,我们一听到建立关系用于查找我们第一反应是建立hashMap,但是在java中的hashMap一下定义那么多关系,书写时比较麻烦的,我们可以用字符串数组来代替hashMap来实现建立这个关系,用数组的下标(数字)来对应数组内容(字符串)。
我们这个问题在运用深度优先搜索对于前几个题不同的是,不是每个位置放置的内容可以相互交换,而是每个位置的数字对应的字符串依次放在对应位置。
✨ 题目代码:
public List<String> letterCombinations(String digits) {List<String> list = new ArrayList<>();String curStr = "";int len = digits.length();//所需获得字符串的长度DFS(digits,list,curStr,0,len);return list;}String[] strings = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};private void DFS(String digits, List<String> list, String curStr, int digitIdx,int len) {if (len == digitIdx){if (len != 0){list.add(curStr);}return;}//进行深度优先搜索,int num = Integer.parseInt(digits.charAt(digitIdx) + "");//获取当钱位置的数字字符for (char ch: strings[num].toCharArray()) {DFS(digits,list,curStr + ch,digitIdx + 1,len);}}
6.数字组合
原题链接
✨ 题目描述:
给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。
✨ 题目案例:
案例1:
输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。
案例2:
输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]
案例3:
输入: candidates = [2], target = 1
输出: []
✨ 题目解析:
我们这个题目也是用DFS进行解决。我们对一个数字进行递归,直到这个组合的数字和大于等于目标数字的时候我们进行终止继续向下搜索,我们需要进行回溯到上一个步骤,试试其他的数字怎么样。
下面就是案例1的DFS过程:
这个问题为了避免出现一个组合重复出现的情况,我们可以在DSF的时候,循环遍历从该数字对应字符串的位置往后进行搜索。
✨ 解题代码:
DFS求解,需要注意的是:allRet.add(new ArrayList<>(curRet)); 其中两个对象的类型都是List,所以我们得转化为 ArrayList<>()这种具体类
public List<List<Integer>> combinationSum(int[] candidates, int target) {List<List<Integer>> allRet = new ArrayList<>(new ArrayList<>());List<Integer> curRet = new ArrayList<>();int curSum = 0;//搜索当前情况下的数字和int prev = 0;//当前你所需要的DFS时加和的下标DFS(candidates,target,allRet,curRet,curSum,prev);return allRet;}private void DFS(int[] candidates, int target, List<List<Integer>> allRet, List<Integer> curRet, int curSum, int prev) {if (curSum >= target){if (curSum == target){//保存当前的解集allRet.add(new ArrayList<>(curRet));}return;}//累加的起始位置为上一项的位置for (int i = prev; i < candidates.length; i++) {//累加当前项curRet.add(candidates[i]);DFS(candidates,target,allRet,curRet,curSum + candidates[i],i);//回溯curRet.remove(curRet.size() - 1);}}
7. 活字印刷
原题链接
✨ 题目描述:
你有一套活字字模 tiles,其中每个字模上都刻有一个字母 tiles[i]。返回你可以印出的非空字母序列的数目。
注意:本题中,每个活字字模只能使用一次。
✨ 题目案例:
案例1:
输入:“AAB”
输出:8
解释:可能的序列为 “A”, “B”, “AA”, “AB”, “BA”, “AAB”, “ABA”, “BAA”。
案例2:
输入:“AAABBC”
输出:188
案例3:
输入:“V”
输出:1
提示:
- 1 <= tiles.length <= 7
- tiles 由大写英文字母组成
✨ 题目分析:
该题目一样是用DFS来进行解题。但是改题目不一样的地方是每个活字字模只能使用一次,也就是每个位置的字符只能用一次,我们为了避免出现一个位置的字符进行多次出现,我们可以创建一个标记数组来标记是否该位置的字符已经在搜索过程中被使用到了。
✨ 解题代码:
public int numTilePossibilities(String tiles) {Set<String> set = new HashSet<>();String curStr = "";int[] book = new int[tiles.length()];//标记字符串中的字符是否已经搜索过了。DFS(tiles,set,curStr,book);return set.size();}private void DFS(String tiles, Set<String> set, String curStr, int[] book) {if (curStr.length() != 0){set.add(curStr);}if (curStr.length() == tiles.length()){return;}for (int i = 0; i < tiles.length(); i++) {if (book[i] == 0){book[i] = 1;//进行深度优先搜索DFS(tiles,set,curStr + tiles.charAt(i),book);//进行回溯book[i] = 0;}}}
8. N皇后
✨ 题目描述:
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
✨ 题目案例:
案例1:
输入:n = 4输出:[[“.Q…”,“…Q”,“Q…”,“…Q.”],[“…Q.”,“Q…”,“…Q”,“.Q…”]]
解释:如上图所示,4 皇后问题存在两个不同的解法。
案例2:
输入:n = 1
输出:[[“Q”]]
✨ 题目分析:
我们就以案例1,来进行DFS分析如下图:
改图中展示 了找到其中一种n皇后的摆法,其他摆法也是按照这种思路进行DFS和回溯。
我们现在最主要的是如何进行判断该位置是否是违规的位置。我们从横纵方向+斜主对角线的坐标,进行了以下分析:
横:x坐标相同
纵:y坐标相同
正对角线:newX - newY = x - y(坐标差相同)
斜对角线:newX + newY == x + y(坐标和相同)
我们就可以针对已经摆放好的皇后来进行判断该位置是否违法,不违法就可以摆放新的皇后,摆放皇后的数量等于n就是一种摆放方式。
✨ 解题代码:
class pair{public int x;public int y;public pair(int x, int y) {this.x = x;this.y = y;}
}
class Solution {public List<List<String>> solveNQueens(int n) {List<List<pair>> allRet = new ArrayList<>();List<pair> curRet = new ArrayList<>();DFS(allRet,curRet,0,n);//System.out.println(allRet.toString());return transResult(allRet,n);}void DFS(List<List<pair>> allRet,List<pair> curRet,int curRow,int n){//如果每一行都没有冲突,则是一种可行方案if (curRow == n){allRet.add(new ArrayList<>(curRet));return;}//确定当前行的每一个位置是否和已经确定的位置有冲突for (int i = 0; i < n; i++) {if(isValidPos(curRet,curRow,i)){curRet.add(new pair(curRow,i));//把当前位置存放到当前情况中//处理下一行DFS(allRet,curRet,curRow + 1,n);//回溯curRet.remove(curRet.size() - 1);//尾删}}}private boolean isValidPos(List<pair> curRet, int row, int col) {for (pair pos: curRet) {if (pos.y == col || pos.x + pos.y == row + col|| pos.x - pos.y == row - col){return false;}}return true;}private List<List<String>> transResult(List<List<pair>> allRet, int n) {List<List<String>> allMet = new ArrayList<>();for (List<pair> curRet : allRet) {List<String> curMat = new ArrayList<>();for (pair pos: curRet) {StringBuilder str = new StringBuilder();for (int i = 0; i < n; i++) {str.append('.');}str.setCharAt(pos.y,'Q');curMat.add(str.toString());}allMet.add(curMat);}return allMet;}}
相关文章:

[算法和数据结构]--回溯算法之DFS初识
回溯算法——DFSDFS介绍(Depth First Search)DFS经典题目1. 员工的重要性2. 图像渲染3.被围绕的区域4.岛屿数量5. 电话号码的字母组合6.数字组合7. 活字印刷8. N皇后DFS介绍(Depth First Search) 回溯法(back tracking)(探索与回溯法&#x…...

【LeetCode每日一题】——680.验证回文串 II
文章目录一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【解题思路】七【题目提示】八【时间频度】九【代码实现】十【提交结果】一【题目类别】 贪心算法 二【题目难度】 简单 三【题目编号】 680.验证回文串 II 四【题目描述】 给你一个字…...

【C语言进阶:指针的进阶】你真分得清sizeof和strlen?
本章重点内容: 字符指针指针数组数组指针数组传参和指针传参函数指针函数指针数组指向函数指针数组的指针回调函数指针和数组面试题的解析这篇博客 FLASH 将带大家一起来练习一些容易让人凌乱的题目,通过这些题目来进一步加深和巩固对数组,指…...

【前端必看】极大提高开发效率的网页 JS 调试技巧
大家好,我是前端西瓜哥。本文讲解如何使用浏览器提供的工具进行 JS 代码的断点调试。 debugger 在代码中需要打断点的地方,加上 debugger,表示一个断点。浏览器代码执行到该位置时,会停下来,进入调试模式。 示例代码…...

【春招面经】视源股份前端一面
前言 本次主要记录一下视源股份CVTE前端一面 (3.3下午4点15) 文章目录前言本次主要记录一下视源股份CVTE前端一面 (3.3下午4点15)问题总结介绍一下项目的来源以及做这个项目的初衷一直监听滚动,有没有对性能产生影响&a…...

插件化开发入门
一、背景顾名思义,插件化开发就是将某个功能代码封装为一个插件模块,通过插件中心的配置来下载、激活、禁用、或者卸载,主程序无需再次重启即可获取新的功能,从而实现快速集成。当然,实现这样的效果,必须遵…...

tftp、nfs 服务器环境搭建
目录 一、认识 tftp、nfs 1、什么是 tftp? 2、什么是 nfs? 3、tftp 和 nfs 的区别 二、tftp的安装 1、安装 tftp 服务端 2、配置 tftp 3、启动 tftp 服务 三、nfs 的安装 1、安装 nfs 服务端 2、配置 nfs 3、启动 nfs 服务 一、认识 tftp、…...

汇编系列03-不借助操作系统输出Hello World
每天进步一点点,加油! 上一节,我们通过汇编指令,借助操作系统的系统调用实现了向标准输出打印Hello world。这一节我们打算绕过操作系统,直接在显示屏幕上打印Hello world。 计算机的启动过程 当我们给计算机加电启…...

TPU编程竞赛系列|算能赛道冠军SO-FAST团队获第十届CCF BDCI总决赛特等奖!
近日,第十届中国计算机学会(CCF)大数据与计算智能大赛总决赛暨颁奖典礼在苏州顺利落幕,算能赛道的冠军队伍SO-FAST从2万余支队伍中脱颖而出,获得了所有赛道综合评比特等奖! 本届CCF大赛吸引了来自全国的2万…...

【C++】AVL树,平衡二叉树详细解析
文章目录前言1.AVL树的概念2.AVL树节点的定义3.AVL树的插入4.AVL树的旋转左单旋右单旋左右双旋右左双旋AVL树的验证AVL树的删除AVL树的性能前言 前面对map/multimap/set/multiset进行了简单的介绍,在其文档介绍中发现,这几个容器有个共同点是࿱…...

C/C++开发,无可避免的多线程(篇四).线程与函数的奇妙碰撞
一、函数、函数指针及函数对象 1.1 函数 函数(function)是把一个语句序列(函数体, function body)关联到一个名字和零或更多个函数形参(function parameter)的列表的 C 实体,可以通过返回或者抛…...
elisp简单实例: taglist
从vim 转到emacs 下,一直为缺少vim 中的tablist 插件而感到失落. 从网上得到的一个emacs中的taglist, 它的功能很简陋,而且没有任何说明, 把它做为elisp的简单实例,供初学者入门倒不错,我给它加了很多注释,帮助理解, 说实话,感觉这百行代码还是挺有深度的,慢慢体会,调试才会有收…...
Azure AI基础到实战(C#2022)-认知服务(3)
目录 OpenFileDialog 类上一节代码的API剖析ComputerVisionClientExtensions.ReadAsync MethodReadHeaders ClassReadHeaders.OperationLocation Property探索ReadHeaders加上调试代码可用于 Azure 认知服务的身份验证标头使用单服务订阅密钥进行身份验证使用多服务订阅密钥进行…...

aws apigateway 使用restapi集成lambda
参考资料 代理集成,https://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html非代理集成,https://docs.aws.amazon.com/zh_cn/apigateway/latest/developerguide/getting-started-…...

HTML基础
HTML 基础 文章目录HTML 基础列表标签无序列表有序列表自定义列表表格标签表格基本标签表格基本结构表格完整结构:合并行和合并列表单标签input 系列标签属性标签text 标签radio 标签 单选框file 标签 文件选择button 标签 按钮input系列标签总结button按钮标签sele…...
ThreadPoolExecutor参数 keepAliveTime allowCoreThreadTimeOut
/*** Timeout in nanoseconds for idle threads waiting for work.* Threads use this timeout when there are more than corePoolSize* present or if allowCoreThreadTimeOut. Otherwise they wait* forever for new work.*/ private volatile long keepAliveTime;等待工作的…...
什么是Hibernate框架?
简单介绍:Hibernate框架是当今主流的java持久层框架之一,是一个开放源码的ORM(Object Relational Mapping,对象关系映射)框架,它对JDBC进行了轻量级的封装,使得JAVA开发人员可以使用面向对象的编…...

指针面试笔试题练习
前言 🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯 c语言进阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:介绍c语言中有关指针更深层的知识. 金句分享: ✨星光…...

docker(三)仓库的搭建、官方私有仓库的加密和认证
文章目录一、docker仓库二、仓库Registry工作原理三、搭建本地私有仓库四、配置镜像加速器五、私有仓库的加密认证1.非加密下上传拉取2.insecure registry3.仓库加密4.仓库认证一、docker仓库 什么是仓库 Docker 仓库是用来包含镜像的位置,Docker提供一个注册服务器…...

FPGA实现SDI视频编解码 SDI接收发送,提供2套工程源码和技术支持
目录1、前言2、设计思路和框架SDI接收SDI缓存写方式处理SDI缓存读方式处理SDI缓存的目的SDI发送3、工程1详解4、工程2详解5、上板调试验证并演示6、福利:工程代码的获取1、前言 FPGA实现SDI视频编解码目前有两种方案: 一是使用专用编解码芯片࿰…...

C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...