C++算法学习心得八.动态规划算法(4)

1.零钱兑换(322题)

题目描述:

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

你可以认为每种硬币的数量是无限的。

示例 1:

  • 输入:coins = [1, 2, 5], amount = 11
  • 输出:3
  • 解释:11 = 5 + 5 + 1

dp[j]:凑足总额为j所需钱币的最少个数为dp[j] 

凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i])

所以dp[j] 要取所有 dp[j - coins[i]] + 1 中最小的。

递推公式:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);

dp[0] = 0;

考虑到递推公式的特性,dp[j]必须初始化为一个最大的数,否则就会在min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖。

所以下标非0的元素都是应该是最大值。

本题求钱币最小个数,那么钱币有顺序和没有顺序都可以,都不影响钱币的最小个数

所以本题并不强调集合是组合还是排列。

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

本题的两个for循环的关系是:外层for循环遍历物品,内层for遍历背包或者外层for遍历背包,内层for循环遍历物品都是可以的

class Solution {
public:int coinChange(vector<int>& coins, int amount) {vector<int>dp(amount + 1,INT_MAX);dp[0] = 0;for(int i = 0;i < coins.size();i++){ // 遍历物品for(int j = coins[i];j <= amount;j++){// 遍历背包if (dp[j - coins[i]] != INT_MAX) { // 如果dp[j - coins[i]]是初始值则跳过dp[j] = min(dp[j - coins[i]] + 1, dp[j]);}}}if (dp[amount] == INT_MAX) return -1;return dp[amount];}
};
  • 时间复杂度: O(n * amount),其中 n 为 coins 的长度
  • 空间复杂度: O(amount)

遍历背包放在外循环,遍历物品放在内循环也是可以的 

class Solution {
public:int coinChange(vector<int>& coins, int amount) {vector<int>dp(amount + 1,INT_MAX);dp[0] = 0;for(int i = 1;i <= amount;i++){ // 遍历背包for(int j = 0;j < coins.size();j++){// 遍历物品if (i-coins[j] >= 0 && dp[i - coins[j]] != INT_MAX) { // 如果dp[j - coins[i]]是初始值则跳过dp[i] = min(dp[i - coins[j]] + 1, dp[i]);}}}if (dp[amount] == INT_MAX) return -1;return dp[amount];}
};

2.完全平方数(279题)

题目描述:

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

示例 1:

  • 输入:n = 12
  • 输出:3
  • 解释:12 = 4 + 4 + 4

dp[j]:和为j的完全平方数的最少数量为dp[j]

dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以凑成dp[j]。

此时我们要选择最小的dp[j],所以递推公式:dp[j] = min(dp[j - i * i] + 1, dp[j]);

dp[0]表示 和为0的完全平方数的最小数量,那么dp[0]一定是0,非0下标的dp[j]一定要初始为最大值,这样dp[j]在递推的时候才不会被初始值覆盖

本题外层for遍历背包,内层for遍历物品,还是外层for遍历物品,内层for遍历背包,都是可以的

先遍历物品,在遍历背包 

class Solution {
public:int numSquares(int n) {vector<int>dp(n + 1,INT_MAX);dp[0] = 0;for(int i = 1;i * i <= n;i++){// 遍历物品for(int j = i * i;j <= n;j++){// 遍历背包dp[j] = min(dp[j],dp[j - i * i]+1);}}return dp[n];}
};

遍历背包,遍历物品

class Solution {
public:int numSquares(int n) {vector<int> dp(n + 1, INT_MAX);dp[0] = 0;for (int i = 0; i <= n; i++) { // 遍历背包for (int j = 1; j * j <= i; j++) { // 遍历物品dp[i] = min(dp[i - j * j] + 1, dp[i]);}}return dp[n];}
};
  • 时间复杂度: O(n * √n)
  • 空间复杂度: O(n)

 3.单词拆分(139题)

题目描述:

给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:

拆分时可以重复使用字典中的单词。

你可以假设字典中没有重复的单词。

示例 1:

  • 输入: s = "leetcode", wordDict = ["leet", "code"]
  • 输出: true
  • 解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。

回溯算法:本道是枚举分割所有字符串,判断是否在字典里出现过

class Solution {
private:bool backtracking (const string& s, const unordered_set<string>& wordSet, int startIndex) {if (startIndex >= s.size()) {return true;}for (int i = startIndex; i < s.size(); i++) {string word = s.substr(startIndex, i - startIndex + 1);if (wordSet.find(word) != wordSet.end() && backtracking(s, wordSet, i + 1)) {return true;}}return false;}
public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet(wordDict.begin(), wordDict.end());return backtracking(s, wordSet, 0);}
};
  • 时间复杂度:O(2^n),因为每一个单词都有两个状态,切割和不切割
  • 空间复杂度:O(n),算法递归系统调用栈的空间

改进版回溯算法:

class Solution {
private:bool backtracking (const string& s,const unordered_set<string>& wordSet,vector<bool>& memory,int startIndex) {if (startIndex >= s.size()) {return true;}// 如果memory[startIndex]不是初始值了,直接使用memory[startIndex]的结果if (!memory[startIndex]) return memory[startIndex];for (int i = startIndex; i < s.size(); i++) {string word = s.substr(startIndex, i - startIndex + 1);if (wordSet.find(word) != wordSet.end() && backtracking(s, wordSet, memory, i + 1)) {return true;}}memory[startIndex] = false; // 记录以startIndex开始的子串是不可以被拆分的return false;}
public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet(wordDict.begin(), wordDict.end());vector<bool> memory(s.size(), 1); // -1 表示初始化状态return backtracking(s, wordSet, memory, 0);}
};

 这个时间复杂度其实也是:O(2^n)

背包问题:

dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词

如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。

所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。

从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。

拆分为一个或多个在字典中出现的单词,所以这是完全背包。

还要讨论两层for循环的前后顺序。

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

本题一定是 先遍历 背包,再遍历物品

class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet(wordDict.begin(), wordDict.end());vector<bool> dp(s.size() + 1, false);dp[0] = true;for (int i = 1; i <= s.size(); i++) {   // 遍历背包for (int j = 0; j < i; j++) {       // 遍历物品string word = s.substr(j, i - j); //substr(起始位置,截取的个数)if (wordSet.find(word) != wordSet.end() && dp[j]) {dp[i] = true;}}}return dp[s.size()];}
};
  • 时间复杂度:O(n^3),因为substr返回子串的副本是O(n)的复杂度(这里的n是substring的长度)
  • 空间复杂度:O(n)

4.多重背包理论基础(卡玛网56题)

有N种物品和一个容量为V 的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci ,价值是Wi 。求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量,且价值总和最大。

#include<iostream>
#include<vector>
using namespace std;int main(){int bagWeight,n;cin >> bagWeight >> n;vector<int> weight(n, 0);vector<int> value(n, 0);vector<int> nums(n, 0);for (int i = 0; i < n; i++) cin >> weight[i];for (int i = 0; i < n; i++) cin >> value[i];for (int i = 0; i < n; i++) cin >> nums[i];vector<int> dp(bagWeight + 1, 0);for(int i = 0; i < n; i++) { // 遍历物品for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量// 以上为01背包,然后加一个遍历个数for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) { // 遍历个数dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i]);}}}cout << dp[bagWeight] << endl;
}

 时间复杂度:O(m × n × k),m:物品种类个数,n背包容量,k单类物品数量

5.打家劫舍( 198题)

题目描述:

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

  • 示例 1:
  • 输入:[1,2,3,1]
  • 输出:4

解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。   偷窃到的最高金额 = 1 + 3 = 4 。

dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]。 

dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])

dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1]);

dp[i] 是根据dp[i - 2] 和 dp[i - 1] 推导出来的,那么一定是从前到后遍历!

class Solution {
public:int rob(vector<int>& nums) {//当前数组大小为0时返回0if (nums.size() == 0)return 0;//当前数组大小1时返回1if (nums.size() == 1)return nums[0];vector<int> dp(nums.size());//定义dp数组dp[0] = nums[0];//初始化0dp[1] = max(nums[0], nums[1]);//初始化dp[1]//遍历,从后向前遍历for (int i = 2; i < nums.size(); i++) {dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);//递推公式}return dp[nums.size() - 1];//返回值}
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

6. 打家劫舍II(213题)

题目描述:

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,能够偷窃到的最高金额。

示例 1:

  • 输入:nums = [2,3,2]

  • 输出:3

  • 解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。

  • 情况一:考虑不包含首尾元素
  • 情况二:考虑包含首元素,不包含尾元素
  • 情况三:考虑包含尾元素,不包含首元素

虽然是考虑包含尾元素,但不一定要选尾部元素,情况二 和 情况三 都包含了情况一了,所以只考虑情况二和情况三就可以了。

class Solution {
public:int rob(vector<int>& nums) {if (nums.size() == 0) return 0;if (nums.size() == 1) return nums[0];int result1 = robRange(nums, 0, nums.size() - 2); // 情况二int result2 = robRange(nums, 1, nums.size() - 1); // 情况三return max(result1, result2);}int robRange(vector<int>& nums,int start,int end){if (end == start) return nums[start];vector<int>dp(nums.size());dp[start] = nums[start];dp[start + 1] = max(nums[start],nums[start + 1]);for(int i = start + 2;i <= end;i++){dp[i] = max(dp[i - 1],dp[i - 2] + nums[i]);}return dp[end];}
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

 7.打家劫舍 III(337题)

题目描述:

在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。

计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。

 本题一定是要后序遍历,如果抢了当前节点,两个孩子就不能动,如果没抢当前节点,就可以考虑抢左右孩子

暴力递归

class Solution {
public:int rob(TreeNode* root) {if(root == NULL)return NULL;if(root->left == NULL && root->right == NULL)return root->val;// 偷父节点int val1 = root->val;if(root->left)val1 += rob(root->left->left) + rob(root->left->right);// 跳过root->left,相当于不考虑左孩子if(root->right)val1 += rob(root->right->left) + rob(root->right->right);// 跳过root->right,相当于不考虑右孩子了// 不偷父节点int val2 = rob(root->left) + rob(root->right);return max(val1, val2);}
};
  • 时间复杂度:O(n^2),这个时间复杂度不太标准,也不容易准确化,例如越往下的节点重复计算次数就越多
  • 空间复杂度:O(log n),算上递推系统栈的空间

记忆化递推:可以使用一个map把计算过的结果保存一下,这样如果计算过孙子了,那么计算孩子的时候可以复用孙子节点的结果。 

class Solution {
public:unordered_map<TreeNode* , int> umap; // 记录计算过的结果int rob(TreeNode* root) {if (root == NULL) return 0;if (root->left == NULL && root->right == NULL) return root->val;if (umap[root]) return umap[root]; // 如果umap里已经有记录则直接返回// 偷父节点int val1 = root->val;if (root->left) val1 += rob(root->left->left) + rob(root->left->right); // 跳过root->leftif (root->right) val1 += rob(root->right->left) + rob(root->right->right); // 跳过root->right// 不偷父节点int val2 = rob(root->left) + rob(root->right); // 考虑root的左右孩子umap[root] = max(val1, val2); // umap记录一下结果return max(val1, val2);}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(log n),算上递推系统栈的空间

动态规划

 这道题目算是树形dp的入门题目,因为是在树上进行状态转移

这里的返回数组就是dp数组

dp数组(dp table)以及下标的含义:下标为0记录不偷该节点所得到的的最大金钱,下标为1记录偷该节点所得到的的最大金钱。

dp数组就是一个长度为2的数组

在递归的过程中,系统栈会保存每一层递归的参数

在遍历的过程中,如果遇到空节点的话,很明显,无论偷还是不偷都是0,所以就返回,相当于dp数组的初始化,明确的是使用后序遍历。

通过递归左节点,得到左节点偷与不偷的金钱。

通过递归右节点,得到右节点偷与不偷的金钱。

如果是偷当前节点,那么左右孩子就不能偷,val1 = cur->val + left[0] + right[0]; (如果对下标含义不理解就再回顾一下dp数组的含义

如果不偷当前节点,那么左右孩子就可以偷,至于到底偷不偷一定是选一个最大的,所以:val2 = max(left[0], left[1]) + max(right[0], right[1]);

最后当前节点的状态就是{val2, val1}; 即:{不偷当前节点得到的最大金钱,偷当前节点得到的最大金钱}

class Solution {
public:int rob(TreeNode* root) {vector<int> result = robTree(root);return max(result[0], result[1]);}// 长度为2的数组,0:不偷,1:偷vector<int> robTree(TreeNode* cur) {if (cur == NULL) return vector<int>{0, 0};vector<int> left = robTree(cur->left);vector<int> right = robTree(cur->right);// 偷cur,那么就不能偷左右节点。int val1 = cur->val + left[0] + right[0];// 不偷cur,那么可以偷也可以不偷左右节点,则取较大的情况int val2 = max(left[0], left[1]) + max(right[0], right[1]);return {val2, val1};}
};
  • 时间复杂度:O(n),每个节点只遍历了一次
  • 空间复杂度:O(log n),算上递推系统栈的空间

总结:

零钱兑换:不同面额的硬币 coins 和一个总金额 amount,凑成总金额所需的最少的硬币个数,dp[j]:凑足总额为j所需钱币的最少个数为dp[j] ,递推公式:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);dp[0] = 0;dp[j]必须初始化为一个最大的数,否则就会在min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖,下标非0的元素都是应该是最大值,本题的两个for循环的关系是:外层for循环遍历物品,内层for遍历背包或者外层for遍历背包,内层for循环遍历物品都是可以的,我们最后返回dp[amount]即可,如果dp[j - coins[i]]是初始值则跳过判断条件,

完全平方数:给定一个整数,使用完全平方数来实现和为这个整数,dp[j]:和为j的完全平方数的最少数量为dp[j],最小的dp[j],所以递推公式:dp[j] = min(dp[j - i * i] + 1, dp[j]),dp[0]一定是0,非0下标的dp[j]一定要初始为最大值,本题外层for遍历背包,内层for遍历物品,还是外层for遍历物品,内层for遍历背包,都是可以的。

for(int i = 1;i * i <= n;i++){// 遍历物品
            for(int j = i * i;j <= n;j++){// 遍历背包
                dp[j] = min(dp[j],dp[j - i * i]+1);
            }
        }

 单词拆分:给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。回溯算法:本道是枚举分割所有字符串,判断是否在字典里出现过,组合问题,我们首先对字符串进行取哈希表的方法,unordered_set<string> wordSet,然后是组合问题,startindex,终止条件if(startindex > s.size())return true;for(int i = startindex;i<s.size();i++)之后我们需要对这个进行取字符串操作,s.substr操作,然后我们进行下面的操作,判断是否出现过且进行递归,然后返回True,否则返回false,使用背包来解决问题,dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false,本题一定是 先遍历 背包,再遍历物品,

多重背包理论基础:有N种物品和一个容量为V 的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci ,价值是Wi 。求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量,且价值总和最大。

for(int i = 0; i < n; i++) { // 遍历物品
        for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
            // 以上为01背包,然后加一个遍历个数
            for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) { // 遍历个数
                dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i]);
            }
        }
    }

打家劫舍: 给定一个数组,然后限制条件是相邻的有警报系统,可以偷取的最大价值是多少,dp[i]:考虑下标i(包括i)以内的房屋,最多可以偷窃的金额为dp[i]dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]),dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1]);从前到后遍历,这里我们定义dp数组大小为数组大小即可,初始化和上述介绍,遍历从前向后遍历,从2开始到nums.size(),最后递推公式即可,最后返回dp[nums.size() - 1]

打家劫舍II:该题与上一个题不同于整个数组是连成一个圈首尾呼应,三种情况第一个不考虑首尾,第二种考虑首不考虑尾,第三种情况考虑尾不考虑首,第二三种情况包括了第一种情况,所以我们直接考虑设计一个函数根据首尾位置的一个打家劫舍的函数即可实现,这里采用两个首尾位置下标的方法,首先递推公式和上一个一样,这里初始化需要根据下标进行初始化,初始化也就是把初始化的下标换成start即可,最后返回dp[end]即可,

打家劫舍III:和二叉树联系起来的一个打家劫舍问题,这里一定需要后序遍历,抢了当前节点,两个孩子就不能动,如果没抢当前节点,就可以考虑抢左右孩子,分两种情况取考虑,这里需要知道一个是取父节点(之后我们需要左节点的左右孩子,还要右节点的左右孩子),另一个是不取父节点(递归左和右)记忆化递推:可以使用一个map把计算过的结果保存一下,这样如果计算过孙子了,那么计算孩子的时候可以复用孙子节点的结果,树形dp是在树上进行状态转移,dp数组下标为0记录不偷该节点所得到的的最大金钱,下标为1记录偷该节点所得到的的最大金钱。dp数组就是一个长度为2的数组,如果是偷当前节点,那么左右孩子就不能偷,val1 = cur->val + left[0] + right[0]; (如果对下标含义不理解就再回顾一下dp数组的含义)如果不偷当前节点,那么左右孩子就可以偷,至于到底偷不偷一定是选一个最大的,所以:val2 = max(left[0], left[1]) + max(right[0], right[1]);最后当前节点的状态就是{val2, val1}; 即:{不偷当前节点得到的最大金钱,偷当前节点得到的最大金钱}其实这里就是将其分开讨论了,最后取最大值即可。

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

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

相关文章

代码随想录|Day21|回溯01|77.组合

77.组合 组合问题不考虑顺序&#xff0c;例如 [1, 2] 和 [2, 1] 是同一个组合。其中 n 为取数的范围&#xff0c;每个组合包含 k个 元素数量&#xff0c;所以我们嵌套 k 个 for循环 可以很容易写出暴力解法。但如果 k 的值过大&#xff0c;代码将会非常冗长。 我们考虑回溯&…

easyExcel 导入、导出Excel 封装公共的方法

文档包含三部分功能 1、easyExcel 公共导出list<对象>方法&#xff0c;可以自定义excel中第一行和样式 2、easyExcel 导入逻辑&#xff0c;结合spring Validator 验证导入数据是否符合规范 3、easyExcel 自定义导出 list<map> 、 list<对象> &#xff08;可…

KBP210-ASEMI新能源专用整流桥KBP210

编辑&#xff1a;ll KBP210-ASEMI新能源专用整流桥KBP210 型号&#xff1a;KBP210 品牌&#xff1a;ASEMI 封装&#xff1a;KBP-4 正向电流&#xff08;Id&#xff09;&#xff1a;2A 反向耐压&#xff08;VRRM&#xff09;&#xff1a;1000V 正向浪涌电流&#xff1a;6…

BswM模块配置指导

文章目录 BswM配置的分类自动配置:通信控制Rule:CC_ComMChannel_Rx自动配置:Ecu状态处理自动配置:模块初始化其他配置总结BswM模块是基础软件的模式管理模块,模式/状态控制都是由BswM模块进行,其实现的方式是通过 “请求-仲裁-执行”三步完成。本篇基于基本Can通信所用到…

Vue3--条件与循环

Vue主要通过v-if和v-for两个指令来控制DOM元素的生成、移除和批量展示。 v-if v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值的时候被渲染。 <h1 v-if"awesome">Vue is awesome!</h1> //当awesome是假值时&#xff0c;h1标签将…

01背包 与 emo题目背景(周超人的遗憾) 的爱恨情仇

本题背景有意思&#xff0c;大家当乐子看&#xff0c;目前没有找到题目原题&#xff0c;也没有写过完全是01背包模板的题目&#xff0c;该篇文章大家注意其01背包一维写法的模板就好&#xff0c;注意各个关键点 ✨欢迎来到脑子不好的小菜鸟的文章✨ &#x1f388;创作不易&…

算力,承载AI无限可能

年后不久&#xff0c;美国人工智能研究公司OpenAI推出的Sora模型引起了广泛关注&#xff0c;对于人工智能发展之快的感慨还未过去&#xff0c;3月初&#xff0c;Anthropic丢出一颗“王炸”Claude3&#xff0c;其中Claude 3 Opus宣称在基准测试中优于OpenAI的GPT-4和Google的Gem…

MyBatis Plus(代码生成器)

一、安装 安装MyBatisPlus插件 二、配置 1、 在生成代码之前首先需要配置所要连接的数据库 下面所对应的分别是&#xff1a; 所要连接的数据库 数据库驱动 用户名 密码 2、 点击Other->Code Generator 开始配置所需选项

VMWare虚拟机使用openmediavault搭建NAS服务器完整步聚

下载: gopenmediavault - The open network attached storage solution 下载好openmediavault的ISO镜像后,打开虚拟机并安装 系统类型选择Debian 启动虚拟机并安装openmediavault 选择中文 地区选中国 键盘配置选汉语 开始安装 配置网络信息 配置root密码 确认密码 系统安装中…

【算法刷题 | 栈】3.16(有效的括号、删除字符串中的所有相邻重复项、逆波兰表达式求值)

文章目录 1.有效的括号1.1题目1.2解法&#xff1a;栈 2.删除字符串中的所有相邻重复项2.1题目2.2解法&#xff1a;栈 3.逆波兰表达式求值3.1题目3.2解法&#xff1a;栈 1.有效的括号 1.1题目 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff…

每日学习笔记:C++ STL 的map、multimap

定义 特点 操作函数 意思就是&#xff0c;使用tuple中的元素来初始化pair&#xff0c;即string(“hello”)、complex(3.4,7.8) 元素的移除讨论

jS 正则

概念 正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript中&#xff0c;正则表达式也是对象。这些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、matchAll、replace、search 和 split 方法。 创建正则表达式 两种方法&#xff1a;字面量方式、构造…