LeetCode 每周算法 6(图论、回溯)

embedded/2024/9/25 23:19:17/

LeetCode 每周算法 6(图论、回溯)

图论算法

在这里插入图片描述

class Solution:  def dfs(self, grid: List[List[str]], r: int, c: int) -> None:  """  深度优先搜索函数,用于遍历并标记与当前位置(r, c)相连的所有陆地(即值为"1"的格子)为已访问(即标记为0)。  :param grid: 二维网格,其中的每个元素都是'0'或'1'。  :param r: 当前遍历到的行索引。  :param c: 当前遍历到的列索引。  """  grid[r][c] = '0'  # 将当前位置标记为已访问(即陆地变为水)  nr, nc = len(grid), len(grid[0])  # 获取网格的行数和列数  # 遍历当前位置的上下左右四个相邻位置  for x, y in [(r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)]:  # 检查相邻位置是否在网格范围内且为陆地(即值为'1')  if 0 <= x < nr and 0 <= y < nc and grid[x][y] == "1":  self.dfs(grid, x, y)  # 递归地遍历相邻的陆地  def numIslands(self, grid: List[List[str]]) -> int:  """  计算给定网格中的岛屿数量。  :param grid: 二维网格,其中的每个元素都是'0'或'1'。  :return: 网格中的岛屿数量。  """  nr = len(grid)  if nr == 0:  # 如果网格为空,则岛屿数量为0  return 0  nc = len(grid[0])  # 获取网格的列数  num_islands = 0  # 初始化岛屿数量为0  for r in range(nr):  # 遍历网格的每一行  for c in range(nc):  # 遍历网格的每一列  if grid[r][c] == "1":  # 如果当前位置是陆地  num_islands += 1  # 岛屿数量加1  self.dfs(grid, r, c)  # 调用dfs函数遍历并标记与当前陆地相连的所有陆地  return num_islands  # 返回岛屿数量

在这里插入图片描述

class Solution:  def orangesRotting(self, grid: List[List[int]]) -> int:  R, C = len(grid), len(grid[0])  # 获取网格的行数和列数  # 初始化一个队列,用于存放腐烂橙子(值为2)的位置及其腐烂时间(初始为0)  queue = deque()  for r, row in enumerate(grid):  for c, val in enumerate(row):  if val == 2:  queue.append((r, c, 0))  # 定义一个辅助函数,用于生成当前橙子位置(r, c)的上下左右四个相邻位置  def neighbors(r, c):  for nr, nc in ((r - 1, c), (r, c - 1), (r + 1, c), (r, c + 1)):  if 0 <= nr < R and 0 <= nc < C:  # 确保相邻位置在网格范围内  yield nr, nc  d = 0  # 初始化腐烂时间计数器  while queue:  # 当队列不为空时,继续执行  r, c, d = queue.popleft()  # 从队列中取出腐烂橙子的位置及其腐烂时间  for nr, nc in neighbors(r, c):  # 遍历当前腐烂橙子的四个相邻位置  if grid[nr][nc] == 1:  # 如果相邻位置是新鲜的橙子  grid[nr][nc] = 2  # 将其标记为腐烂的橙子  queue.append((nr, nc, d + 1))  # 将其加入队列,并更新腐烂时间为当前时间+1  # 检查网格中是否还有新鲜的橙子(值为1)  if any(1 in row for row in grid):  return -1  # 如果有,说明无法让所有橙子都腐烂,返回-1  return d  # 否则,返回最后的腐烂时间

在这里插入图片描述

class Solution:  def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:  # 创建一个defaultdict来存储课程的邻接表,即每个课程的后继课程列表  edges = collections.defaultdict(list)  # 创建一个列表来存储每个课程的入度(即有多少课程是该课程的前置课程)  indeg = [0] * numCourses  # 遍历先决条件列表,构建邻接表和入度列表  for info in prerequisites:  # info[1] 是当前课程,info[0] 是其前置课程  # 将当前课程(info[1])的后继课程(info[0])添加到邻接表中  edges[info[1]].append(info[0])  # 将前置课程(info[0])的入度加1  indeg[info[0]] += 1  # 创建一个双端队列,用于存储入度为0的课程(即没有前置课程的课程)  q = collections.deque([u for u in range(numCourses) if indeg[u] == 0])  # 初始化已访问(或已完成)的课程数  visited = 0  # 使用广度优先搜索(BFS)遍历课程  while q:  # 每从队列中取出一个课程,表示该课程可以完成  visited += 1  u = q.popleft()  # 遍历当前课程的所有后继课程  for v in edges[u]:  # 将后继课程的入度减1,表示完成了一个前置课程  indeg[v] -= 1  # 如果后继课程的入度变为0,说明其所有前置课程都已完成,可以加入队列继续搜索  if indeg[v] == 0:  q.append(v)  # 如果已访问的课程数等于总课程数,说明所有课程都可以完成  # 否则,存在环,无法完成所有课程  return visited == numCourses

在这里插入图片描述

class Trie:  def __init__(self):  # 初始化Trie节点,children是一个长度为26的列表,# 用于存储指向子节点的引用(假设只处理小写字母a-z)  # 每个位置对应一个字母(例如,0对应'a',1对应'b',...,25对应'z')  # isEnd用于标记该节点是否是某个单词的结尾  self.children = [None] * 26  self.isEnd = False  def searchPrefix(self, prefix: str) -> "Trie":  # 搜索并返回给定前缀对应的最后一个Trie节点  # 如果前缀不存在于Trie中,则返回None  node = self  # 从根节点开始搜索  for ch in prefix:  # 将字符转换为对应的索引('a'->0, 'b'->1, ..., 'z'->25)  ch = ord(ch) - ord("a")  # 如果当前节点的children中对应字符的节点不存在,说明前缀不存在,返回None  if not node.children[ch]:  return None  # 否则,移动到子节点继续搜索  node = node.children[ch]  # 如果所有字符都成功匹配,返回最后一个节点  return node  def insert(self, word: str) -> None:  # 将一个单词插入到Trie中  node = self  # 从根节点开始插入  for ch in word:  # 将字符转换为对应的索引  ch = ord(ch) - ord("a")  # 如果当前节点的children中对应字符的节点不存在,则创建一个新的Trie节点  if not node.children[ch]:  node.children[ch] = Trie()  # 移动到子节点继续插入  node = node.children[ch]  # 标记最后一个节点为单词的结尾  node.isEnd = True  def search(self, word: str) -> bool:  # 搜索Trie中是否存在一个完整的单词  # 使用searchPrefix找到最后一个节点,然后检查该节点是否是某个单词的结尾  node = self.searchPrefix(word)  return node is not None and node.isEnd  def startsWith(self, prefix: str) -> bool:  # 检查Trie中是否存在以给定前缀开头的单词  # 使用searchPrefix找到最后一个节点,如果找到,则说明存在以该前缀开头的单词  return self.searchPrefix(prefix) is not None# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)

图论算法

在这里插入图片描述

class Solution {  
public:  // 回溯函数,用于生成所有排列  // res: 存储所有排列的二维向量  // output: 当前排列的向量,通过修改它来生成新的排列  // first: 当前需要确定位置的索引(从0开始)  // len: 输入数组nums的长度,即需要排列的元素总数  void backtrack(vector<vector<int>>& res, vector<int>& output, int first, int len) {  // 如果已经处理完所有元素(即已经填充了所有位置),则将当前排列添加到结果中if (first == len) {  // 使用emplace_back直接在res的末尾构造一个output的副本res.emplace_back(output);  return;  }  // 从first开始,遍历所有未确定位置的元素for (int i = first; i < len; ++i) {  // 将当前位置的元素与first位置的元素交换,// 这样可以尝试将不同的元素放在first位置  swap(output[i], output[first]);  // 递归地处理下一个位置(first+1)backtrack(res, output, first + 1, len);  // 回溯,撤销上一步的交换,以便尝试其他可能性swap(output[i], output[first]);  }  }  // 公开接口,用于生成给定数组nums的所有排列  // nums: 需要排列的整数数组  // 返回值: 包含所有排列的二维向量  vector<vector<int>> permute(vector<int>& nums) {  vector<vector<int>> res; // 初始化结果向量// 从第一个元素开始回溯,直到处理完所有元素    backtrack(res, nums, 0, (int)nums.size());return res; // 返回所有排列的集合  }  
};

在这里插入图片描述

// 迭代法实现子集枚举
class Solution {  
public:  // 用于临时存储当前子集的结果  vector<int> output;  // 用于存储所有子集的结果  vector<vector<int>> ans;  // 生成给定整数数组nums的所有子集  vector<vector<int>> subsets(vector<int>& nums) {  // 遍历所有可能的位掩码,从0到2^nums.size() - 1  // 每个位掩码都代表一个子集,其中1表示选择该位置的元素,0表示不选择  for (int mask = 0; mask < (1 << nums.size()); ++mask) {  // 清空output,为构建新的子集做准备  output.clear();  // 遍历nums中的每个元素及其对应的位掩码位  for (int i = 0; i < nums.size(); ++i) {  // 如果mask的第i位是1(即mask & (1 << i)不为0),则将nums[i]加入当前子集  if (mask & (1 << i)) {  output.push_back(nums[i]);  }  }  // 将构建好的子集添加到结果集中  ans.push_back(output);  }  // 返回包含所有子集的结果集  return ans;  }  
};// 递归法实现子集枚举
// class Solution {  
// public:  
//     vector<int> output; // 用于临时存储当前子集的结果  
//     vector<vector<int>> ans; // 用于存储所有子集的结果  //     // 回溯函数,从数组的第first个元素开始构建子集  
//     // first 表示当前正在处理的元素在nums中的索引  
//     // nums 是给定的整数数组  
//     void backtrack(int first, vector<int>& nums) {  
//         // 如果已经处理了nums中的所有元素,则将当前子集添加到结果集中  
//         if (first == nums.size()) {  
//             ans.push_back(output);  
//             return;  
//         }  //         // 选择当前元素加入子集  
//         output.push_back(nums[first]);  
//         // 递归处理下一个元素,继续构建子集  
//         backtrack(first + 1, nums);  //         // 回溯,撤销选择当前元素,尝试不包含当前元素的情况  
//         output.pop_back();  
//         backtrack(first + 1, nums); 
//     }  //     // 主函数,用于生成nums的所有子集  
//     vector<vector<int>> subsets(vector<int>& nums) {  
//         backtrack(0, nums);  
//         return ans;  
//     }  
// }; 

在这里插入图片描述

class Solution {  
public:  // 主函数,用于生成给定数字字符串的所有字母组合  vector<string> letterCombinations(string digits) {  if (digits.empty()) { // 如果输入的数字字符串为空,则直接返回空的组合列表  return combinations;  }  string combination; // 用于存储当前正在构建的字母组合  vector<string> combinations; // 存储所有可能的字母组合  // 创建一个哈希表,将数字映射到它们对应的字母字符串  unordered_map<char, string> phoneMap{  {'2', "abc"},  {'3', "def"},  {'4', "ghi"},  {'5', "jkl"},  {'6', "mno"},  {'7', "pqrs"},  {'8', "tuv"},  {'9', "wxyz"}  };  // 调用回溯函数来生成所有可能的组合  backtrack(combinations, phoneMap, digits, 0, combination);  return combinations; // 返回所有生成的字母组合  }  // 回溯函数,用于递归地生成所有可能的字母组合  void backtrack(vector<string>& combinations, const unordered_map<char, string>& phoneMap, const string& digits, int index, string& combination) {  if (index == digits.length()) { // 如果已经处理完所有数字,则将当前组合添加到结果列表中  combinations.push_back(combination);  } else {  char digit = digits[index]; // 获取当前正在处理的数字  const string& letters = phoneMap.at(digit); // 从哈希表中获取该数字对应的字母字符串  for (const char& letter: letters) { // 遍历该数字对应的所有字母  combination.push_back(letter); // 将当前字母添加到当前组合中  // 递归调用回溯函数,处理下一个数字,同时传入更新后的组合  backtrack(combinations, phoneMap, digits, index + 1, combination);  combination.pop_back(); // 回溯,撤销上一步的添加操作,以便尝试下一个字母  }  }  }  
};

在这里插入图片描述

class Solution {  
public:  // 用于存储所有可能的组合结果的向量  vector<vector<int>> result;  // 用于在回溯过程中构建当前路径的向量  vector<int> path;  // 回溯函数,用于生成所有可能的组合  // candidates: 候选数字的集合  // target: 目标值,需要找到的和  // start: 从哪个候选数字开始考虑(避免重复使用相同的数字)  void backtrack(const vector<int>& candidates, int target, int start) {  // 如果当前目标和已经小于0,说明当前路径不可行,直接返回  if (target < 0) return;  // 如果目标和为0,说明找到了一个有效的组合,将其添加到结果中  if (target == 0) {  result.push_back(path);  return;  }  // 遍历候选数字,从start开始,确保不重复使用数字,并且当前数字不超过目标和  for (int i = start; i < candidates.size() && target - candidates[i] >= 0; i++) {  // 将当前数字添加到路径中  path.push_back(candidates[i]);  // 递归调用,目标值减去当前数字,start仍为i,因为可以重复使用相同的数字  // 注意:在某些问题中,可能需要将start改为i+1来避免重复使用相同的数字  backtrack(candidates, target - candidates[i], i);  // 回溯,撤销选择,继续尝试其他可能  path.pop_back();  }  }  // 主函数,用于找到所有可以使数字和为target的组合  // candidates: 候选数字的集合  // target: 目标值  // 返回值: 所有可能的组合  vector<vector<int>> combinationSum(vector<int>& candidates, int target) {  // 对候选数字进行排序,这有助于在回溯过程中剪枝,提高效率  // 特别是当允许重复使用数字时,排序可以确保较小的数字先被考虑  sort(candidates.begin(), candidates.end());  // 调用回溯函数开始搜索  backtrack(candidates, target, 0);  // 返回所有找到的组合  return result;  }  
};

在这里插入图片描述

class Solution {  // 回溯函数,用于生成所有有效的括号组合  // result: 存储所有有效括号组合的字符串向量  // current: 当前正在构建的括号字符串  // left: 当前已使用的左括号数量  // right: 当前已使用的右括号数量  // n: 目标括号对的数量  void backtrack(vector<string>& result, string& current, int left, int right, int n) {  // 如果当前括号字符串的长度达到了目标长度(n对括号即2n个字符)  // 则将其添加到结果向量中  if (current.size() == n * 2) {  result.push_back(current);  return;  }  // 如果还可以添加左括号(即左括号数量小于n)  if (left < n) {  current.push_back('('); // 添加左括号  backtrack(result, current, left + 1, right, n); // 递归调用,左括号数量+1  current.pop_back(); // 回溯,撤销上一步的操作  }  // 如果右括号数量小于左括号数量(保证括号的有效性)  if (right < left) {  current.push_back(')'); // 添加右括号  backtrack(result, current, left, right + 1, n); // 递归调用,右括号数量+1  current.pop_back(); // 回溯,撤销上一步的操作  }  }  public:  // 生成所有可能的、且有效的括号组合的公共接口  // n: 括号对的数量  vector<string> generateParenthesis(int n) {  vector<string> result; // 存储结果的向量  string current; // 当前正在构建的括号字符串  backtrack(result, current, 0, 0, n); // 从无括号开始,调用回溯函数  return result; // 返回所有有效的括号组合  }  
};// class Solution {
//     bool valid(const string& str) {
//         int balance = 0;
//         for (char c: str) {
//             if (c == '(') {
//                 ++balance;
//             } else {
//                 --balance;
//             }
//             if (balance < 0) {
//                 return false;
//             }
//         }
//         return balance == 0;
//     }//     void backtrack(string& current, int n, vector<string>& result) {
//         if (n == current.size()) {
//             if (valid(current)) {
//                 result.push_back(current);
//             }
//             return;
//         }
//         current += '(';
//         backtrack(current, n, result);
//         current.pop_back();
//         current += ')';
//         backtrack(current, n, result);
//         current.pop_back();
//     }
// public:
//     vector<string> generateParenthesis(int n) {
//         vector<string> result;
//         string current;
//         backtrack(current, n * 2, result);
//         return result;
//     }
// };

在这里插入图片描述

class Solution {  
public:  // 判断给定单词是否可以通过在棋盘board上相邻位置上的字母连接而成  bool exist(vector<vector<char>>& board, string word) {  // 遍历棋盘上的每一个位置作为起始点  for (int i = 0; i < board.size(); i++) {  for (int j = 0; j < board[0].size(); j++) {  // 为每个起始点创建一个访问标记矩阵,初始都为false  vector<vector<bool>> visited(board.size(), vector<bool>(board[0].size(), false));  // 从当前位置开始,尝试深度优先搜索以找到单词  if (dfs(board, visited, word, 0, i, j)) return true; // 如果找到单词,则返回true  }  }  // 如果遍历完所有起始点都没有找到单词,则返回false  return false;  }  private:  // 深度优先搜索函数,尝试在棋盘上找到单词  bool dfs(vector<vector<char>>& board, vector<vector<bool>>& visited, const string& word, int str_index, int i, int j) {  // 如果已经匹配完单词的所有字符,说明找到了单词,返回true  if (str_index == word.size()) return true;  // 检查当前位置是否越界、是否已访问过、或者是否与单词的当前字符不匹配  // 如果任何一个条件不满足,则无法继续搜索,返回false  if (i >= board.size() || i < 0 ||  j >= board[0].size() || j < 0 ||  visited[i][j] == true || board[i][j] != word[str_index]) return false;  // 标记当前位置为已访问  visited[i][j] = true;  // 尝试向上、下、左、右四个方向搜索  // 如果在任何一个方向上找到了单词,则返回true  if (dfs(board, visited, word, str_index + 1, i + 1, j) ||  // 向右  dfs(board, visited, word, str_index + 1, i - 1, j) ||  // 向左  dfs(board, visited, word, str_index + 1, i, j + 1) ||  // 向下  dfs(board, visited, word, str_index + 1, i, j - 1)) return true; // 向上  // 如果四个方向都没有找到单词,则回溯,将当前位置标记为未访问  visited[i][j] = false;  // 返回false,表示以当前位置为起始点没有找到单词  return false;  }  
};

在这里插入图片描述

class Solution {  
private:  // f是一个二维动态数组,用于存储字符串s中任意子串[i, j]是否为回文串的布尔值  vector<vector<int>> dp;  // result是一个二维字符串向量,用于存储所有满足条件的分割结果,每个内部向量代表一种分割方式  vector<vector<string>> result;  // answer是一个字符串向量,用于在DFS过程中临时存储当前的分割结果  vector<string> answer;  // n表示字符串s的长度  int n;  public:   // 深度优先搜索函数,用于遍历所有可能的分割方式  // s是当前处理的字符串,i是当前遍历到的起始位置  void dfs(const string& s, int i) {  // 如果遍历到了字符串的末尾,说明找到了一种分割方式,将其添加到结果中  if (i == n) {  result.push_back(answer);  return;  }  // 从当前位置i开始,尝试所有可能的分割点j  for (int j = i; j < n; ++j) {  // 如果子串[i, j]是回文串,则进行下一步分割  if (dp[i][j]) {  // 将当前回文子串添加到答案中  answer.push_back(s.substr(i, j - i + 1));  // 递归调用dfs,从j+1位置开始继续搜索  dfs(s, j + 1);  // 回溯,移除刚刚添加的回文子串,以尝试其他可能的分割  answer.pop_back();  }  }  }  // partition函数是类的公开接口,用于找到并返回所有满足条件的分割方式  vector<vector<string>> partition(string s) {  // 初始化n为字符串s的长度  n = s.size();  // 初始化f数组,默认所有子串都是回文串(之后会通过动态规划更新)  dp.assign(n, vector<int>(n, true));  // 使用动态规划计算f数组,即判断所有子串是否为回文串  for (int i = n - 1; i >= 0; --i) {  for (int j = i; j < n; ++j) {  // 如果首尾字符相等且去掉首尾后的子串也是回文串,则当前子串是回文串  dp[i][j] = (s[i] == s[j] && (j - i <= 1 || dp[i + 1][j - 1]));  }  }  // 从字符串的起始位置开始,使用深度优先搜索遍历所有可能的分割方式  dfs(s, 0);  // 返回所有满足条件的分割结果  return result;  }  
};

在这里插入图片描述

class Solution {  
private:  // 用于存储所有有效的N皇后解决方案  vector<vector<string>> result;  // 回溯函数,尝试在每一行放置皇后,并递归地处理下一行  void backtracking(int n, int row, vector<string>& chessboard) {  // 如果已经处理完所有行,说明找到了一个有效的解决方案,将其添加到结果中  if (row == n) {  result.push_back(chessboard);  return;  }  // 遍历当前行的每一列  for (int col = 0; col < n; col++) {  // 检查在当前位置放置皇后是否有效  if (isvalid(row, col, chessboard, n)) {  // 在当前位置放置皇后  chessboard[row][col] = 'Q';  // 递归处理下一行  backtracking(n, row + 1, chessboard);  // 回溯,撤销在当前位置放置的皇后  chessboard[row][col] = '.';  }  }  }  // 检查在(row, col)位置放置皇后是否有效  // 有效的条件是当前位置所在列、左上方对角线、右上方对角线上没有皇后  bool isvalid(int row, int col, vector<string>& chessboard, int n) {  // 检查列上是否有皇后  for (int i = 0; i < row; i++) {  if (chessboard[i][col] == 'Q') {  return false;  }  }  // 检查左上方对角线上是否有皇后  for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {  if (chessboard[i][j] == 'Q') {  return false;  }  }  // 检查右上方对角线上是否有皇后  for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {  if (chessboard[i][j] == 'Q') {  return false;  }  }  // 如果没有冲突,则当前位置有效  return true;  }  public:  // 主函数,用于解决N皇后问题  // 返回所有有效的N皇后解决方案  vector<vector<string>> solveNQueens(int n) {  // 清除之前的结果  result.clear();  // 初始化棋盘,所有位置都是'.'  vector<string> chessboard(n, string(n, '.'));  // 从第一行开始回溯  backtracking(n, 0, chessboard);  // 返回所有有效的解决方案  return result;  }  
};

http://www.ppmy.cn/embedded/116872.html

相关文章

JAVA-StringBuilder和StringBuffer

一、认识String类 1.认识 String在Java中是字符串类型&#xff0c;但与其他类型不同。它是一个类&#xff0c;可以创建对象的类。与int、char等自待类型有些许不同。但它仍然是java提供的一种类型。 类中有4个属性&#xff0c;这里主要认识一下value属性。它是实际存放字符串…

倒排索引(反向索引)

倒排索引&#xff08;Inverted Index&#xff09;是搜索引擎和数据库管理系统中常用的一种数据结构&#xff0c;用于快速检索文档集合中的文档。在全文搜索场景中&#xff0c;倒排索引是一种非常高效的手段&#xff0c;因为它能够快速定位到包含特定关键词的所有文档。 1、基本…

【算法】贪心+堆排序实现大根堆及标准库容器类的融合使用

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

一种单目标A*算法设计与实现

一种单目标A*算法设计与实现 作者&#xff1a;吴屏珊 最近在学习简单的单目标A*算法&#xff0c;其中在CSDN上阅读到的一篇博文给了我很大启发&#xff0c;于是在该博文的基础上&#xff0c;笔者记录了一点自己对于A*算法的体会和感悟。原文链接 目录 文章目录 一种单目标A*…

【多线程】面试高频考点!JUC常见类的详细总结,建议收藏!

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;多线程 / javaEE初阶 JUC是“Java Util Concurrency”的缩写&#xff0c;指的是Java并发工具包&#xff0c;它位于java.util.concurrent包及其子包中。JUC包提供了大量用于构建并发应用程序的工具和…

如何在openEuler上安装和配置openGauss数据库

本文将详细介绍如何在openEuler 22.03 LTS SP1上安装和配置openGauss数据库&#xff0c;包括数据库的启动、停止、远程连接配置等关键步骤。 1、安装 使用OpenEuler-22.03-LTS-SP1-x64版本的系统&#xff0c;通过命令行安装openGauss数据库。 1.1、确保系统软件包索引是最新…

OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【内核通信机制】上

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 子系统开发内核 轻量系统内核&#xff08;LiteOS-M&#xff09; 轻量系统内核&#…

[图解]静态关系和动态关系

1 00:00:01,060 --> 00:00:04,370 首先我们来看静态关系和动态关系 2 00:00:06,160 --> 00:00:10,040 我们要尽量基于静态关系来建立动态关系 3 00:00:11,740 --> 00:00:13,740 不能够在没有这个的基础上 4 00:00:14,220 --> 00:00:17,370 没有这个的情况下就胡…