2024.06.23 刷题日记

〇、前言

今天重点刷了回溯,以及常见的题目。

46. 全排列

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:

输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:

输入:nums = [1]
输出:[[1]]

这道题目的思路是使用回溯法(Backtracking)来生成所有可能的全排列。回溯法是一种通过递归尝试所有可能的解决方案的算法。在生成排列时,回溯法通过递归地构建排列,当遇到不满足条件的排列时,撤销上一步操作(即回溯),继续尝试其他可能性

思路:

  1. 初始化:创建一个结果列表,用于存储所有可能的排列。还需要一个临时列表来存储当前构建的排列。
  2. 递归函数
    • 基本情况:如果临时列表的长度等于输入数组的长度,说明已经构建了一个完整的排列,将其加入结果列表。
    • 递归情况:遍历输入数组中的每个数字,如果该数字未在当前临时列表中出现过,则将其加入临时列表,然后继续递归构建排列。完成后,撤销这一步操作,从而回溯到上一个状态,继续尝试其他数字。
  3. 回溯:在递归过程中,每当完成一轮递归(即一个完整的排列)后,撤销最后一步操作,回到上一个状态,从而尝试其他可能性。

算法步骤:

  1. 创建一个空的结果列表 res
  2. 定义一个递归函数 backtrack(path, used)
    • 如果 path 的长度等于 nums 的长度,将 path 加入 res 并返回。
    • 遍历 nums 中的每个数字 num,如果 num 未被使用过:
      • num 加入 path
      • 标记 num 为已使用。
      • 递归调用 backtrack 继续构建排列。
      • 递归结束后,撤销当前操作(即移除 path 中的最后一个数字,并将 num 标记为未使用)。
  3. 调用 backtrack([], []) 开始递归。

示例代码:

class Solution {
public:vector<vector<int>> permute(vector<int>& nums) {vector<vector<int>> res;vector<int> path;vector<bool> used(nums.size(), false);backtrack(nums, path, used, res);return res;}private:void backtrack(vector<int>& nums, vector<int>& path, vector<bool>& used, vector<vector<int>>& res) {if (path.size() == nums.size()) {res.push_back(path);return;}for (int i = 0; i < nums.size(); i++) {if (!used[i]) {path.push_back(nums[i]);used[i] = true;backtrack(nums, path, used, res);path.pop_back();used[i] = false;}}}
};

在这里插入图片描述

关键点总结:

  • 使用回溯法构建所有可能的排列。
  • 在递归过程中使用一个 path 列表来存储当前的排列,一个 used 列表来记录哪些数字已经被使用过。
  • 通过回溯撤销之前的选择,从而尝试其他可能性,最终生成所有的排列。

参考:liweiwei1419

47. 全排列 II

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

示例 1:

输入:nums = [1,1,2]
输出: [[1,1,2], [1,2,1], [2,1,1]]

示例 2:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

仔细比较和上一道题目的不同处,对于上一道题目,nums 中并没有相同的元素,这道题目需要考虑相同元素的问题。首先要对 nums 进行一个 sort,目的是遇到和 nums[i-1] 相同时且需要跳过时,就跳过,因此排序很关键。此外,跳过的条件是什么?这是这道题目的核心

nums = [1,1,2] 来举例,当进入第一层递归函数时,used[0] = false,因此path 增长到[1,] 进入第二层递归函数,此时 nums[0] 为 true,因此继续遍历。当 i = 1 时,used[1] = false,因此 path 增长到[1,2,]进入第三层递归。同理nums[0]、nums[1]为 true, i = 2时,path = [1,2,3,] 。进入第四层递归,此时 path.size() == nums.size() ,退出,将 path 收集到 result 中。

返回到第三层递归后,path.pop(),path = [1,2,],且 used = [1,1,0,],此时 i = 2,循环结束,返回第二层,第二层i = 1,继续 pop,此时 path = [1,],used = [1,0,0,]。接着在本层递归中继续遍历,i = 2时,path增长到[1,2,],又进入第三层递归,此时used = [1,0,1],因此 i = 1, path = [1,2,1],used = [1,1,1]。进入第四层递归,收集答案后退回到第三层。继续 pop,此时 path = [1,2,]used = [1,0,1]。继续循环,i = 2时,used[2] = true,循环结束,退回到第二层递归,此时 i= 2,继续 pop,此时 used = [1,0,0],path = [1,],循环结束,退回到第一层。

进入第一层后,此时 i = 0,继续 pop,此时 path = [,],used = [0,0,0],继续循环,i = 1时候,发现了一个问题,这时候很明显需要跳过,因为已经把 nums[0] 搜索过了,这时候再次搜索 nums[1],就会有相同的结果。

因此跳过的条件是: i>0 && nums[i] = nums[i-1] && !nums[i-1],没错就是 nums[i-1]没被用过。

因此算法如下:

class Solution {
public:vector<vector<int>> permuteUnique(vector<int>& nums) {sort(nums.begin(), nums.end()); // 排序,便于跳过重复结果vector<vector<int>> result;vector<int> used(nums.size(), false);vector<int> path;backtrace2(nums, used, path, result);return result;}private:void backtrace2(vector<int>& nums, vector<int>& used, vector<int>& path,vector<vector<int>>& result) {if (path.size() == nums.size()) {result.push_back(path);return;}for (int i = 0; i < nums.size(); i++) {if (used[i])continue;if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])continue; // 如果前一个元素没被用过,说明这是一个新起点,这个起点和前面有相同状态,一定要跳过path.push_back(nums[i]);used[i] = true;backtrace2(nums, used, path, result);path.pop_back();used[i] = false;}}
};

39. 组合总和

给你一个 无重复元素 的整数数组 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
输出: []

这道题目和前面的两道题目有很大的相同点。首先就是元素可以重复使用,其次不允许出现相同的组合 [2,3,3][3,2,2]只能出现一种。也就是说,只能从左向右回溯,因此排序后,递归的时候,需要传入当前节点的下标

这道题目考查的是组合,组合用到了回溯,而在回溯的过程中用到了剪枝来提前结束不可能的分支。我们需要找到所有可能的数字组合,这些组合之和等于给定的目标数 target。具体来说,我们可以定义一个辅助函数来递归地尝试每个可能的数字添加到当前的组合中,并通过递归地调用自身来探索添加后的所有可能路径。

回溯法的主要步骤如下:

  1. 定义递归函数:创建一个递归辅助函数,例如 backtrack,该函数接收当前的组合、当前组合的总和、起始索引和其他必要的参数。

  2. 递归终止条件

    • 当当前组合的总和等于目标数 target 时,将当前组合添加到结果列表中。
    • 当当前组合的总和超过 target 时,终止当前递归路径,因为继续添加任何正整数都将使总和增加。
  3. 遍历和选择

    • 从起始索引开始,遍历 candidates 数组。
    • 将每个元素添加到当前组合中,并递归调用 backtrack 函数,同时将当前元素的索引作为新的起始索引传递,允许同一个元素多次选择。
    • 完成当前元素的探索后,从当前组合中移除该元素(也称为“回溯”),尝试下一个元素。
  4. 实现优化

    • 可以先对 candidates 进行排序,有助于在某些情况下提前终止不必要的路径。
    • 使用引用传递来避免不必要的数据复制,提高效率。

C++ 示例代码:

class Solution {
public:vector<vector<int>> combinationSum(vector<int>& candidates, int target) {sort(candidates.begin(), candidates.end());vector<vector<int>> results;vector<int> currentCombination;backtrack(candidates, target, 0, currentCombination, results);return results;}private:void backtrack(vector<int>& candidates, int remaining, int start, vector<int>& current, vector<vector<int>>& results) {if (remaining == 0) {results.push_back(current);return;}for (int i = start; i < candidates.size(); i++) {if (remaining < candidates[i]) break; // 剪枝current.push_back(candidates[i]);backtrack(candidates, remaining - candidates[i], i, current, results); // 不增加i,允许重复选择同一元素current.pop_back(); // 回溯,移除上一步添加的元素}}
};

这段代码中:

  • backtrack 函数是一个递归函数,用于构建组合。
  • remaining 表示距离目标值还差多少,每次递归调用时都减去当前选择的值。
  • start 用于控制从哪个索引开始遍历 candidates,以允许元素重复使用。
  • current 存储当前的组合。
  • results 存储所有满足条件的组合。

通过递归地尝试每种可能的组合,并通过回溯机制撤销上一步操作,这种方法能有效地找出所有可能的组合,使得它们的和为目标值 target

40. 组合总和 II

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次 。

注意:解集不能包含重复的组合。

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出: [ [1,1,6], [1,2,5],[1,7], [2,6] ]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
输出: [ [1,2,2], [5] ]

这道题是组合总和的一个变种,其中元素在每个组合中只能使用一次,并且解集不能包含重复的组合。这种情况下,我们需要确保每个元素只被使用一次,并且要处理好元素重复出现带来的问题(例如示例中的重复数字 12)。

分析步骤:

  1. 排序:首先对数组进行排序。排序有两个好处:

    • 可以方便地跳过重复的元素,避免生成重复的组合。
    • 在递归中更容易判断并剪枝,当当前组合的和已经超过目标值 target 时,可以停止添加更大的元素。
  2. 回溯法:使用回溯法来寻找所有符合条件的组合。我们需要设计一个递归函数,该函数能够遍历所有可能的组合路径

  3. 递归设计

    • 递归函数参数:需要当前组合 combination、当前的开始位置 start、当前的和 currentSum、目标值 target 和结果集 results
    • 终止条件
      • currentSum 等于 target 时,把 combination 添加到 results 中。
      • currentSum 超过 target 时,直接返回,因为后续的数只会使和更大。
  4. 避免重复:由于题目中的数组可能含有重复元素,我们需要特别处理,以避免在结果集中出现重复的组合:

    • 当遍历到某个元素时,如果它与前一个元素相同,并且前一个元素在这个位置上没有被使用,那么跳过这个元素。
  5. 递归和回溯:在递归过程中,需要尝试包括当前元素在内的所有可能。每次递归后,需要撤销当前的选择(即进行回溯),然后尝试下一个可能的选项。

C++ 示例代码:

class Solution {
public:vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {vector<vector<int>> results;vector<int> combination;sort(candidates.begin(), candidates.end());  // 排序backtrack(candidates, target, 0, combination, results);return results;}private:void backtrack(vector<int>& candidates, int target, int start, vector<int>& combination, vector<vector<int>>& results) {if (target == 0) {results.push_back(combination);return;}for (int i = start; i < candidates.size(); i++) {if (i > start && candidates[i] == candidates[i - 1]) continue;  // 跳过重复元素if (candidates[i] > target) break; combination.push_back(candidates[i]);backtrack(candidates, target - candidates[i], i + 1, combination, results);combination.pop_back();  // 回溯}}
};

这段代码中的关键点是处理重复元素的方式(通过在排序后的数组中跳过相同的连续元素)和确保每个元素在组合中只使用一次(递归调用时 start 参数使用 i + 1)。这样既避免了重复组合的生成,也保证了每种可能的组合都被探索到。

77. 组合

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例 1:

输入:n = 4, k = 2
输出: [ [2,4], [3,4], [2,3], [1,2], [1,3],
[1,4], ]

示例 2:

输入:n = 1, k = 1
输出:[[1]]

这道题目就是简单的组合,利用回溯就可以:

class Solution {
public:vector<vector<int>> combine(int n, int k) {vector<vector<int>> result;vector<int> path;backtrace(1, n, path, result, k);return result;}private:void backtrace(int start, int n, vector<int>& path,vector<vector<int>>& result, int k) {if (path.size() == k) {result.push_back(path);return;}for(int i = start; i <= n; i++){path.push_back(i);backtrace(i+1, n, path, result, k);path.pop_back();}}
};

78. 子集

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

输入:nums = [0]
输出:[[],[0]]

这依然是一道很简单的组合体,只要在进入一次回溯之前将path 存进 result:

class Solution {
public:vector<vector<int>> subsets(vector<int>& nums) {vector<vector<int>> result;vector<int> path;backtrace(nums,0,result,path);return result;}
private:void backtrace(vector<int> &nums,int start,vector<vector<int>> &result,vector<int> &path){result.push_back(path);for(int i = start; i < nums.size(); i++){path.push_back(nums[i]);backtrace(nums,i+1,result,path);path.pop_back();}}};

90. 子集 II

给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的 子集(幂集)。

解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

示例 1:

输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]

示例 2:

输入:nums = [0]
输出:[[],[0]]

这道题目多了一些限制条件,nums 中有重复元素,这样子集求取的时候就要注意不能取重复的值,只要加上这个逻辑就可以了:if(i > start && nums[i] == nums[i-1]) continue;:

class Solution {
public:vector<vector<int>> subsetsWithDup(vector<int>& nums) {sort(nums.begin(),nums.end());vector<vector<int>> result;vector<int> path;backtrace(nums,0,path,result);return result; }
private:void backtrace(vector<int> &nums,int start,vector<int> &path,vector<vector<int>> &result){result.push_back(path);for(int i = start; i < nums.size(); i++){if(i > start && nums[i] == nums[i-1]) continue;path.push_back(nums[i]);backtrace(nums, i+1,path,result);path.pop_back();}}
};

60. 排列序列

给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

“123” “132” “213” “231” “312” “321”

给定 n 和 k,返回第 k 个排列。

示例 1:

输入:n = 3, k = 3
输出:“213”

示例 2:

输入:n = 4, k = 9
输出:“2314”

示例 3:

输入:n = 3, k = 1
输出:“123”

这道题目如果不剪枝,是一道简单题,思路就是回溯所有可能,当找到一种可能的时候,将计数器+1,如果计数器刚好等于 8,就将答案收集起来。这种解法时间复杂度太高,没有剪枝:

在这里插入图片描述

如果加一个 tag,如果到了之后,以后全部 break:

private:int tag = false;void backtrace(int n, int k, vector<int>& path, vector<vector<int>>& result,int& begin, vector<bool>& used) {if (path.size() == n) {begin++;if (begin == k) {result.push_back(path);tag = true;}return;}for (int i = 1; i <= n; i++) {if (tag)break;if (used[i])continue;path.push_back(i);used[i] = true;backtrace(n, k, path, result, begin, used);used[i] = false;path.pop_back();}}
};

也只提升了一点点:
在这里插入图片描述

事实上,可以直接构造,这是一道数学题,不过这不在本节讨论的范围,略过。

93. 复原 IP 地址

有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。

例如:“0.1.2.201” 和 “192.168.1.1” 是 有效 IP 地址,但是 “0.011.255.245”、“192.168.1.312” 和 “192.168@1.1” 是 无效 IP 地址。
给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 ‘.’ 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。

示例 1:

输入:s = “25525511135”
输出:[“255.255.11.135”,“255.255.111.35”]

示例 2:

输入:s = “0000”
输出:[“0.0.0.0”]

示例 3:

输入:s = “101023”
输出:[“1.0.10.23”,“1.0.102.3”,“10.1.0.23”,“10.10.2.3”,“101.0.2.3”]

要解决这个问题,我们可以采用回溯法,这是一种通过构建解决方案的步骤来尝试达到问题的解的方法。对于IP地址生成问题,主要的思路是尝试在字符串s中插入三个点来形成四个有效的十进制数字,每个数字的范围必须在0到255之间,并且不能有前导0(除了数字0本身)。

算法步骤

  1. 初始化:准备一个容器来存放最终的答案。
  2. 递归函数:设计一个递归函数,用于尝试所有可能的点的位置。
    • 参数:当前构建的字符串 current,当前处理的字符串位置 start,已放置的点数 dotCount
  3. 递归终止条件
    • 如果放置了3个点且处理完整个字符串,检查当前构建的IP是否有效,如果有效则加入结果。
    • 如果放置的点数已经达到3个,但还未处理完字符串,或字符串已用尽但点数不足,这条路径就无效。
  4. 递归遍历
    • 从当前位置开始,尝试截取1到3个字符作为一个字段,只要这个字段有效(即转换为数字后在0到255之间,且无前导0),就递归尝试下一个字段。
    • 每次递归尝试放置一个点,直到所有的点都放完为止。
  5. 边界与有效性检查
    • 确保每个部分在转化为数字后不会超过255。
    • 检查字符串部分不应有前导0,除非它就是"0"。
class Solution {
public:vector<string> restoreIpAddresses(string s) {vector<string> result;string ip;backtrack(s, 0, 0, ip, result);return result;}void backtrack(const string& s, int start, int dotCount, string ip, vector<string>& result) {if (dotCount == 3) { // 最后一段if (isValid(s, start, s.length() - 1)) {result.push_back(ip + s.substr(start));}return;}for (int i = start; i < s.length() && i < start + 3; ++i) {if (isValid(s, start, i)) {string next = ip + s.substr(start, i - start + 1) + (dotCount < 3 ? "." : "");backtrack(s, i + 1, dotCount + 1, next, result);}}}bool isValid(const string& s, int start, int end) {if (start > end) return false;if (s[start] == '0' && start != end) return false; // 前导0int num = 0;for (int i = start; i <= end; ++i) {if (s[i] < '0' || s[i] > '9') return false; // 非数字num = num * 10 + (s[i] - '0');if (num > 255) return false;}return true;}
};

这段代码中:

  • backtrack 递归函数用于构建和探索所有可能的IP地址组成。
  • isValid 函数检查一个IP地址的一部分是否为有效的数字(即没有前导零,且位于0到255之间)。

通过这种方式,我们可以生成所有可能的有效IP地址,并且避免不必要的计算和检查,使算法效率较高。

总结

你提供了九道题,每道题都侧重于不同的回溯策略。这些题目都是对回溯法的典型应用,展示了如何解决涉及排列、组合、子集生成和特定格式(如IP地址)生成的问题。下面是对这些题目的详细总结:

1. 全排列 (LeetCode 46)

思路:

  • 递归地尝试每个数字,如果未使用则加入当前路径,继续递归直到路径长度等于数组长度。

2. 全排列 II (LeetCode 47)

思路:

  • 先排序以简化重复值处理。
  • 使用额外的条件检查以跳过相同数字的重复处理。

3. 组合总和 (LeetCode 39)

思路:

  • 从数组中选择元素,允许元素重复使用,直到当前组合的和等于目标值。

4. 组合总和 II (LeetCode 40)

思路:

  • 与组合总和类似,但每个元素只能使用一次。
  • 跳过重复元素以避免重复的组合。

5. 组合 (LeetCode 77)

思路:

  • 回溯生成从1到n的所有可能的k个数的组合。

6. 子集 (LeetCode 78)

思路:

  • 从左到右逐个添加元素,每次添加时生成新的子集。

7. 子集 II (LeetCode 90)

思路:

  • 类似于子集,但要处理重复元素,需要先排序并在递归过程中跳过重复的元素。

8. 排列序列 (LeetCode 60)

思路:

  • 通过计算阶乘数,直接确定第k个排列的每一位,而非生成所有排列。

9. 复原 IP 地址 (LeetCode 93)

思路:

  • 尝试在给定字符串中插入3个点,分割成四部分,验证每部分是否为有效的IP段。

关键技巧和策略:

  1. 回溯基本框架: 使用递归函数进行深度优先搜索,每一步都尝试当前可用的选择,然后进入下一层递归。完成一种方案后,撤销当前步骤(回溯),尝试下一个可能的选项。
  2. 处理重复元素:
    • 对数组进行排序,使得相同的元素都相邻,然后在递归过程中通过比较当前元素与前一个元素来跳过重复处理。
  3. 剪枝优化:
    • 在递归之前判断是否可能形成有效解,如组合总和中和超过目标值时停止递归。
  4. 利用位置索引:
    • 通过传递当前元素的索引来避免重新使用已处理的元素,尤其是在需要组合或排列的题目中。

这些题目展示了回溯法在处理需要枚举所有可能情况的问题时的强大能力。适当的剪枝可以显著提高效率,避免不必要的计算。在处理包含重复元素的数组时,合理的跳过策略是必须的,以保证结果的唯一性。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Node.js是什么(基础篇)

前言 Node.js是一个基于Chrome V8 JavaScript引擎的开源、跨平台JavaScript运行时环境&#xff0c;主要用于开发服务器端应用程序。它的特点是非阻塞I/O模型&#xff0c;使其在处理高并发请求时表现出色。 一、Node JS到底是什么 1、Node JS是什么 Node.js不是一种独立的编程…

C/C++ - 编码规范(USNA版)

[IC210] Resources/C Programming Guide and Tips 所有提交的评分作业&#xff08;作业、项目、实验、考试&#xff09;都必须使用本风格指南。本指南的目的不是限制你的编程&#xff0c;而是为你的程序建立统一的风格格式。 * 这将有助于你调试和维护程序。 * 有助于他人&am…

USB - USB在消费领域的应用

Switching in USB Consumer Applications 通用串行总线&#xff08;USB&#xff09;已成为满足终端设备之间日益增长的快速数据传输需求的主流接口--例如&#xff0c;在个人电脑和便携式设备&#xff08;如手机、数码相机和个人媒体播放器&#xff09;之间下载和上传数据。 The…

Go WebSocket入门+千万级别弹幕系统架构设计

Go实现WebSocket&#xff08;千万级别弹幕系统架构设计&#xff09; 1 websocket简介(基于HTTP协议的长连接) 使用WebSocket可以轻松的维持服务器端长连接&#xff0c;其次WebSocket是架构在HTTP协议之上的&#xff0c;并且也可以使用HTTPS方式&#xff0c;因此WebSocket是可靠…

国产化操作系统杂谈

目录 操作系统国产化背景国产化操作系统名录优秀操作系统介绍1.深度Linux&#xff08;deepin&#xff09;2.FydeOS3.AliOS&#xff08;openAliOS&#xff09;4.openEuler5.红旗Linux6. startOS 总结 操作系统国产化背景 官方的说法是为了打破长期以来国外对中国的操作系统的垄…

OGG几何内核开发-复杂装配模型读取、显示、分析

OGG几何内核读取STEP模型文件的API有STEPCAFControl_Reader、STEPControl_Reader。 STEPCAFControl_Reader使用很复杂&#xff0c;但可以展示装配树&#xff0c;有利于模型的详细分析。 本文演示了《插件化算法研究平台V2》的OCC几何模型插件的部分功能&#xff1a;显示装配树…

四川汇聚荣科技有限公司靠谱吗?

在如今这个信息爆炸的时代&#xff0c;了解一家公司是否靠谱对于消费者和合作伙伴来说至关重要。四川汇聚荣科技有限公司作为一家位于中国西部地区的企业&#xff0c;自然也受到了人们的关注。那么&#xff0c;这家公司究竟如何呢?接下来&#xff0c;我们将从多个角度进行深入…

Python应用开发——30天学习Streamlit Python包进行APP的构建(8)

st.table 显示静态表格。 这与 st.dataframe 的不同之处在于,这里的表格是静态的:其全部内容直接显示在页面上。 Function signature[source]st.table(data=None) Parametersdata (pandas.DataFrame, pandas.Styler, pyarrow.Table, numpy.ndarray, pyspark.sql.DataFrame,…

Mysql数据库约束的概述 , 逐渐约束 , 主键自增 , 表关系的概念和外键 ,多表关系约束介绍和使用

约束和表设计 1、DQL查询语句-limit语句(掌握) 目标 能够掌握limit语句的使用 讲解 作用&#xff1a; LIMIT是限制的意思&#xff0c;所以LIMIT的作用就是限制查询记录的条数。 LIMIT语句格式: select * from 表名 limit offset, row_count; mysql中limit的用法&#…

面试题4:POST 比 GET 安全?

不是。HTTP就没有加密功能。 我们知道 GET一般将参数放到URL的查询字符串中&#xff0c;如果是实现登录页面&#xff0c;我们的用户名和密码就直接显示到浏览器的地址栏中了&#xff0c;此时就会轻易的被他人获取账号密码&#xff0c;很不安全。而POST会把参数放到 body 里&am…

Flutter框架高阶——Window应用程序设置窗体窗口背景完全透明

文章目录 1.修改 main.cpp1&#xff09;C 与 Win32 API2&#xff09;EnableTransparency()3&#xff09;中文注释 2.编写 Flutter 代码1&#xff09;bitsdojo_window2&#xff09;window_manager3&#xff09;区别对比4&#xff09;同时使用&#xff08;1&#xff09;设置初始化…

winRar去广告记录

效果&#xff1a;双击winRar.exe&#xff0c;不会弹出广告窗口&#xff0c;但会弹出使用时间许可警告&#xff0c;效果不是很完美。 工具&#xff1a;everything.exe&#xff08;非必须&#xff09;、sublime text&#xff08;非必须&#xff09;、spyxx.exe&#xff08;非必须…

【Python】已解决:pymssql引发的MSSQLDatabaseException错误

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;pymssql引发的MSSQLDatabaseException错误 一、分析问题背景 在Python中使用pymssql库与Microsoft SQL Server数据库交互时&#xff0c;有时会遇到pymssql._mss…

系统安全设计规范(Word原件)

1.1安全建设原则 1.2 安全管理体系 1.3 安全管理规范 1.4 数据安全保障措施 1.4.1 数据库安全保障 1.4.2 操作系统安全保障 1.4.3 病毒防治 1.5安全保障措施 1.5.1实名认证保障 1.5.2 接口安全保障 1.5.3 加密传输保障 1.5.4终端安全保障 资料获取&#xff1a;私信或者进主页。…

Redis数据库的删除和安装

Redis数据库的删除和安装 1、删除Redis数据库2、下载Redis数据库 1、删除Redis数据库 没有下载过的&#xff0c;可以直接跳到下面的安装过程↓ 我们电脑中如果有下载过Redis数据库&#xff0c;要更换版本的话&#xff0c;其实Redis数据库的删除是比较简单的&#xff0c;打开我…

微型操作系统内核源码详解系列五(五):cm3下Pendsv切换任务上篇

系列一&#xff1a;微型操作系统内核源码详解系列一&#xff1a;rtos内核源码概论篇&#xff08;以freertos为例&#xff09;-CSDN博客 系列二&#xff1a;微型操作系统内核源码详解系列二&#xff1a;数据结构和对象篇&#xff08;以freertos为例&#xff09;-CSDN博客 系列…

Bilibili开源发布轻量级 Index 系列语言模型:2.8T 训练数据,支持角色扮演

Bilibili首次发布 Index 系列模型中的轻量版本&#xff1a;Index-1.9B 系列 本次开源的 Index-1.9B系列包含以下模型&#xff1a; Index-1.9Bbase:基座模型&#xff0c;具有 19 亿 非词嵌入参数量&#xff0c;在 2.8T 中英文为主的语料上预训练&#xff0c;多个评测基准上与…

已解决java.util.concurrent.BrokenBarrierException异常的正确解决方法,亲测有效!!!

已解决java.util.concurrent.BrokenBarrierException异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 问题分析 出现问题的场景 报错原因 解决思路 解决方法 分析错误日志 检查线程中断 设置合理的等待时间 优化代码逻辑 使用同步…

[数据概念|方案实操]清华数据大讲堂5-数据要素化治理的理论方法与工程实践

“ 数据要素化是资产化的重要前提和实现路径” 鼹鼠哥公众号链接在 [数据概念|方案实操]清华数据大讲堂5-数据要素化治理的理论方法与工程实践 (qq.com) 2024年6月5日&#xff0c;清华数据大讲堂第五讲开讲。 中国电子信息产业集团副总 陆志鹏 以《数据要素化治理的理论方法与…