动态规划刷题总结(入门)

目录

什么是动态规划算法

如何判断题目中将使用动态规划算法?

动态规划题目做题步骤

动态规划题目解析

泰波那契数模型

第 N 个泰波那契数

三步问题 

使用最小花费爬楼梯 

路径问题 

不同路径 

不同路径 Ⅱ 

珠宝的最高价值 

下降最短路径和 

地下城游戏 

简单多状态问题

按摩师

打家劫舍 Ⅱ 

删除并获得点数 

粉刷房子 

复杂多状态问题

买卖股票的最佳时机含冷冻期

买卖股票的最佳时机含手续费

买卖股票的最佳时机 Ⅲ 

买卖股票的最佳时机 Ⅳ 

子数组问题 

最大子数组和

环形子数组的最大和 

乘积最大数组


什么是动态规划算法

动态规划(Dynamic programming)是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的算法。 动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。

如何判断题目中将使用动态规划算法?

当分析问题的过程中,出现重复子问题,例如下面的问题:

三步问题

小孩多次重复上楼这个动作,问最多的方式

使用最小花费爬楼梯

要计算出达到楼顶的最低花费,先要求出 楼顶 - 1  或 楼顶 - 2  位置的最低花费 

不同路径

需要到达星星位置,就要先到达 1/2 的位置,要达到 1/2 的位置,需要先达到 1/2 的各自得左边或上边,依次类推......

最大子数组和

以 i 位置为结尾的数组中和最大的子数组,与以 i - 1位置为结尾的数组中和最大的子数组也由一定的关系,但关系或许不是绝对的,需要分析

动态规划题目做题步骤

动态规划类题目做题步骤一般分为 5 步

  • 状态表示

将需要的状态填入 dp 表中,这个状态一般是根据 题目要求 + 经验得出的。其中,线性 dp 表填 dp[i] 的经验为:以 i 位置为结尾, +(题意)或者 以 i 位置为开头,+ (题意)这里的题意,一般指题目中要求的东西。比如:使用最小花费爬楼梯问题中,dp[i] 就表示:爬到 i 位置时的最小花费;最大子数组和问题中,dp[i] 就表示以 i 位置为结尾的数组中最大的和

当然,dp 表也有可能是二维,甚至三维,具体需看题意,比如,不同路径中就需要 dp[i][j] 表示走到坐标为 [i, j] 位置时的路径数。

  • 状态转移方程

状态转移方程就是填 dp 表的关键,通俗的来说就是 dp[i] 等于什么,通过距离 i 位置最近的一步,来划分问题,如通过 dp[i - 1]、dp[i + 1]、dp[i - 2] 等等,如果状态转移方程写不出来,就要思考状态表示的正确性了。

  • 初始化

初始化 dp 数组,是为了防止填写 dp 表的时候发生越界。

  • 确定填表顺序

有的 dp表是从坐往右依次填,有的是从右往左依次填,取决于定义 dp 表时的状态表示。

  • 确定返回值

既然选择了使用动态规划解决这道问题,那么最终答案一定会直接或间接通过 dp 表产生!

动态规划题目解析

动态规划算法写代码的步骤比较固定:

  • 创建 dp 表
  • 初始化(保证填表的时候不越界)
  • 填表顺序及填表,保证填当前状态的时候,所需要的状态已经计算过了
  • 返回值

将 dp 表多开一列,一般是为了方便初始化,但多开一列后要注意原数组的下标需要与 dp 表有对应关系,再一个就是多开的那一列填的值必须保证 dp 表的填写正确!

泰波那契数模型

第 N 个泰波那契数

第 N 个泰波那契数

这道题是动态规划的基础,一定要好好理解这道题目!

class Solution {
public:int tribonacci(int n) {vector<int> dp(n + 1); // dp[i] 表示第 i 个泰波那契数列if(n == 0) return 0;if(n == 1|| n == 2) return 1;dp[0] = 0, dp[1] = 1, dp[2] = 1;// 由题意得:状态转移方程为 :dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];for(int i = 3; i <= n; i++){dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];}return dp[n];}
};

三步问题 

三步问题

 泰波那契数模型

class Solution {
public:int waysToStep(int n) {const int MOD = 1e9 + 7;vector<int> dp(n + 1);// 初始化 dp 表,防止越界if(n == 1) return 1;if(n == 2) return 2;if(n == 3) return 4;dp[1] = 1, dp[2] = 2, dp[3] = 4;for(int i = 4; i <= n; i++){dp[i] = ((dp[i - 1] + dp[i - 2])%MOD + dp[i - 3])%MOD;}return dp[n];}
};

使用最小花费爬楼梯 

使用最小花费爬楼梯

class Solution {
public:int minCostClimbingStairs(vector<int>& cost) {int n = cost.size();vector<int> dp(n);// dp[i] 表示以 i 位置为起点,到达楼顶的最小花费dp[n - 1] = cost[n - 1], dp[n - 2] = cost[n - 2];for(int i = n - 3; i >= 0; i--){dp[i] = min(cost[i] + dp[i + 1], cost[i] + dp[i + 2]);//可以从 i - 1 位置或者 i - 2 位置到达 i 位置,取其中花费最小的}return min(dp[0], dp[1]);}
};

路径问题 

不同路径 

不同路径

使用二维 dp 表解决,只需要处理好初始化即可! 

class Solution {
public:int uniquePaths(int m, int n) {vector<vector<int>> dp(m + 1, vector<int>(n + 1));dp[0][1] = 1; // 初始化,其余多开的地方全部为 0 for(int i = 1; i <= m; i++){for(int j = 1; j <= n; j++){// dp[i][j] 表示走到走到 i 行 j 列为结尾的路径总数(加上一行一列的情况下)dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}return dp[m][n];}
};

不同路径 Ⅱ 

 不同路径 II

这道题目相比于 不同路径 ,在方格中添加了障碍物,一但在路上遇到了障碍物,那么这条路就走不通了,这个 i,j 位置的 dp表的值就要置 0,并且 i, j 位置的 dp 值会一直影响后面的 dp 值,最终影响最终结果! 

class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int m = obstacleGrid.size();int n = obstacleGrid[0].size();vector<vector<int>> dp(m + 1, vector<int>(n + 1));dp[0][1] = 1;for(int i = 1; i <= m; i++){for(int j = 1; j <= n; j++){dp[i][j] = dp[i - 1][j] + dp[i][j - 1];if(obstacleGrid[i - 1][j - 1]) dp[i][j] = 0;}}  return dp[m][n];}
};

珠宝的最高价值 

珠宝的最高价值

这道题目的思路其实也挺简单的,相对于普通的二维 dp 中加入了一次判断大小的过程。

class Solution {
public:int jewelleryValue(vector<vector<int>>& frame) {int m = frame.size();int n = frame[0].size();// dp[i][j]为加上扩展的数组,到达第第 i 行,第 j 列时的最大价值vector<vector<int>> dp(m + 1, vector<int>(n + 1));       for(int i = 1; i <= m; i++){for(int j = 1; j <= n; j++){dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + frame[i - 1][j - 1]; }}return dp[m][n];}
};

下降最短路径和 

 下降路径最小和

这道题就要认真对 dp 表多开的那一列做初始化了!但如果不多开一列的话,边界条件可能会更难处理。为了在状态转移方程中求最小值的时候不被多开的那一列干扰,可以初始化为 INT_MAX

class Solution {
public:int minFallingPathSum(vector<vector<int>>& matrix) {int m = matrix.size();int n = matrix[0].size();vector<vector<int>> dp(m + 1, vector<int>(n + 2));for(int i = 1; i <= m; i++) dp[i][0] = INT_MAX; // 初始化for(int i = 1; i <= m; i++) dp[i][n + 1] = INT_MAX; for(int i = 1; i <= m; i++){for(int j = 1; j <= n; j++){dp[i][j] = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i - 1][j + 1])) + matrix[i - 1][j - 1];}}int min_path = INT_MAX;for(int j = 1; j <= n; j++){if(dp[m][j] < min_path) min_path = dp[m][j];}return min_path;}
};

地下城游戏 

地下城游戏

这道题就采用了以 i,j 位置为起点的做法,这种做法比较方便计算。当然也可以使用以 i,j 位置为终点的 dp 思路,但需要开两个 dp 表,而且处理起来比较的复杂,不推荐。地下城游戏 

class Solution {
public:int calculateMinimumHP(vector<vector<int>>& dungeon){int m = dungeon.size();int n = dungeon[0].size();vector<vector<int>> dp(m + 1, vector<int>(n + 1));// dp[i][j] 表示从 [i,j] 位置过后,到达终点所需要的最小健康点数for(int i = 0; i <= m; i++) dp[i][n] = INT_MAX;for(int j = 0; j <= n; j++) dp[m][j] = INT_MAX;dp[m][n -1] = dp[m - 1][n] = 1; // 保证计算出 i, j 位置救到公主的时候,起码要有 1 滴血for(int i = m -1; i >= 0; i--){for(int j = n - 1; j >= 0; j--){dp[i][j] = min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j];dp[i][j] = max(1, dp[i][j]);// 如果 dp[i][j] 计算下来小于 0 ,说明后面有大血包,以至于在当前位置血量为负都行,但这是不符合游戏规则的// 所以到 i,j 位置时,起码得有 1 健康值 }}return dp[0][0];}
};

简单多状态问题

多状态问题,即 dp[i] 位置的状态,可能不只有一种,可能有多种情况,这些情况都要考虑进去!

按摩师

按摩师

dp[i] 的状态表示,填写都需要经过多方面思考。 

class Solution {
public:int massage(vector<int>& nums) {int n = nums.size();if(n == 0) return 0;vector<int> dpf(n), dpg(n);// dpf[i] 表示选择到 i 位置的时候,这个值 选, 得到的最大时长// dpg[i] 表示选择到 i 位置的时候,这个值不选,得到的最大时长dpf[0] = nums[0], dpg[0] = 0;for(int i = 1; i < n; i++){dpf[i] = dpg[i - 1] + nums[i];dpg[i] = max(dpf[i - 1], dpg[i - 1]);// dpg[i] i 位置不选, i - 1 位置也可能不选也可能选 ,看哪个值最大就选哪个}return max(dpf[n - 1], dpg[n - 1]);}
};

打家劫舍 Ⅱ 

 打家劫舍 II

这道题的多种状态为:小偷是否偷第一间房,如果他偷了第一间,那就不能偷第二间,最后一间,所以只需要在 [3, n - 1] 之间找出最高金额,再加上第一间的金额即可;如果他没有偷第一间,那就是再 [2,n] 之间找出最高金额,最后再找出求出的这两个最高金额中最大的那个即可。

class Solution {
public:int rob(vector<int>& nums) {int n = nums.size();// 两种状态计算的方式相同,找出最大的那个即可!return max(nums[0] + _rob(nums, 2, n - 2), _rob(nums, 1, n - 1));}int _rob(vector<int>& nums, int left, int right){if(left > right) return 0;int n = nums.size();vector<int> f(n); // 表示偷的 dp 表vector<int> g(n); // 表示不偷的 dp 表f[left] = nums[left];for(int i = left + 1; i <= right; i++){// 两表之间需要相互计算,因此需要一起填表f[i] = g[i - 1] + nums[i];g[i] = max(f[i - 1], g[i - 1]);}return max(f[right], g[right]);}
};

删除并获得点数 

删除并获得点数

先排序,找出最大的数,并将所有的数映射到数组,再利用“打家劫舍”的多状态思路解决问题。

class Solution {
public:int deleteAndEarn(vector<int>& nums) {sort(nums.begin(), nums.end());int n = *(nums.end() - 1); // 求出 nums 中最大的元素,方便开 arr 数组vector<int> arr(n + 1, 0);  // 相当于将点数相邻的计数并放在一起了for(auto x: nums) arr[x] += x; // 将 x 的 '和' 全部映射在 arr 数组里// 利用 “打家劫舍” 的思路, 求出能获得的最大点数vector<int> f(n + 1); // 获得这个位置的点数,并不获得相邻位置的点数vector<int> g(n + 1); // 不获得这个位置的点数for(int i = 1; i <= n; i++){f[i] = g[i - 1] + arr[i];g[i] = max(g[i - 1], f[i - 1]);}return max(f[n], g[n]);}
};

粉刷房子 

粉刷房子

以 i 位置为结尾的最小花费,当前位置的颜色只需要与前一个位置不同即可,在这个条件下求最小花费,i 位置可以有三个颜色,因此有三种状态需要考虑,他们都可能出现不同的结果,最终选择最小的那个。

class Solution {
public:int minCost(vector<vector<int>>& costs) {int m = costs.size();int n = costs[0].size();// dp[i] 表示刷到第 i 个房子时的最小花费// 但dp[i] 又可以继续细分为 多种状态  vector<vector<int>> dp(m + 1, vector<int>(n));for(int i = 1; i <= m; i++){dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]) + costs[i - 1][0]; // i 位置为 红dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + costs[i - 1][1]; // i 位置为 蓝dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + costs[i - 1][2]; // i 位置为 绿}return min(dp[m][0], dp[m][1], dp[m][2]);}
};

复杂多状态问题

买卖股票的最佳时机含冷冻期

买卖股票的最佳时机含冷冻期

如果子状态比较多且相互影响难以分析,可以画状态转移图,必须搞清楚状态之间的关系!

class Solution {
public:int maxProfit(vector<int>& prices) {// dp[i] 表示第 i 天时,你的最大利润// dp[i] 可以细分 为三种
//dp[i][0] 表示第 i 天结束时处于买入状态,dp[i][1] 第 i 天结束处于可交易状态,dp[i][2] 第 i 天结束处于冷冻期状态int m = prices.size();if(m == 1) return 0;vector<vector<int>> dp(m + 1, vector<int>(3));dp[0][0] -= prices[0];for(int i = 1; i <= m; i++){// 如果子状态关系不好分析, 可以画状态转移表// 状态之间又关系且可能互相影响dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i - 1]);dp[i][1] = max(dp[i - 1][1], dp[i - 1][2]);dp[i][2] = dp[i - 1][0] + prices[i - 1]; cout << dp[i][0] << " " << dp[i][1] << " " << dp[i][2] << endl;}return max(dp[m][1], dp[m][2]);}
};

买卖股票的最佳时机含手续费

买卖股票的最佳时机含手续费

class Solution {
public:int maxProfit(vector<int>& prices, int fee) {// dp[i] 表示第 i 天结束时,获得的最大利润int m = prices.size();vector<vector<int>> dp(m + 1, vector<int>(2, 0));// 0 代表第 i 天结束后,处于买入状态,1 代表卖出状态dp[0][0] -= prices[0];for(int i = 1; i <= m; i++){dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i - 1]);dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i - 1] - fee);} return dp[m][1];}
};

买卖股票的最佳时机 Ⅲ 

买卖股票的最佳时机 III

用循环限制交易次数即可!

class Solution {
public:const int INF = 0x3f3f3f3f; // 初始化第一行, 为了后续求 max 的时候,不影响后续的结果!int maxProfit(vector<int>& prices) {int m = prices.size();// dp[i] 表示在第 i 天结束时获得的最大利润// dp[i] 可以分为好几个状态vector<vector<int>> f(m, vector<int>(3, -INF)); // 买入状态vector<vector<int>> g(m , vector<int>(3, -INF)); // 卖出状态f[0][0] = -prices[0], g[0][0] = 0;for(int i = 1; i < m; i++){for(int j = 0; j < 3; j++)// j 表示参与交易的次数{f[i][j] = max(f[i - 1][j], g[i - 1][j] - prices[i]);g[i][j] = g[i - 1][j];if(j - 1 >= 0)  g[i][j] = max(g[i - 1][j], f[i - 1][j - 1] + prices[i]);}}int ret = 0;for(int j = 0; j < 3; j++) ret = max(ret, g[m - 1][j]);return ret;}
};

买卖股票的最佳时机 Ⅳ 

 买卖股票的最佳时机 IV

与限制次数为 2 次是相同的做法,用循环 k 次保证所有交易次数和状态能得到结果。

class Solution {
public:const int INF = 0x3f3f3f3f; // 初始化第一行, 为了后续求 max 的时候,不影响后续的结果!int maxProfit(int k, vector<int>& prices) {int m = prices.size();k = min(k, m / 2);// dp[i] 表示在第 i 天结束时获得的最大利润// dp[i] 可以分为好几个状态vector<vector<int>> f(m, vector<int>(k + 1, -INF)); // 买入状态vector<vector<int>> g(m , vector<int>(k + 1, -INF)); // 卖出状态f[0][0] = -prices[0], g[0][0] = 0;for(int i = 1; i < m; i++){for(int j = 0; j <= k; j++) // 为什么要用 k 来循环,保证一共交易 j 次, 每次都有对应的最大利润{f[i][j] = max(f[i - 1][j], g[i - 1][j] - prices[i]);g[i][j] = g[i - 1][j];if(j - 1 >= 0)  g[i][j] = max(g[i - 1][j], f[i - 1][j - 1] + prices[i]);}}int ret = 0;for(int j = 0; j <= k; j++) ret = max(ret, g[m - 1][j]);return ret;}
};

子数组问题 

最大子数组和

最大子数组和

class Solution {
public:int maxSubArray(vector<int>& nums) {// dp[i]:以 i 位置为结尾的数组的最大子数组和int n = nums.size();vector<int> dp(n + 1);dp[0] = 0;for(int i = 1; i <= n; i++){dp[i] = max(nums[i - 1], dp[i - 1] + nums[i - 1]);}// 不一定以 n - 1 位置为结尾时,子数组的和最大int ret = dp[1];for(int i = 1; i <= n; i++) if(dp[i] > ret) ret = dp[i];return ret;}
};

环形子数组的最大和 

 环形子数组的最大和

将结果分为两种,一种是不包含头尾的状态,一种是包含头尾的状态,包含头尾就需要使用正难则反的思想,将问题变为数组内进行操作! 

class Solution {
public:int maxSubarraySumCircular(vector<int>& nums) {const int INF = 0x3f3f3f3f;int n = nums.size();// 环形 dp 问题, 转化为非环形// 1. 目标子数组未连接头尾,直接求最大连续子数组的和// 2. 目标子数组连接头尾,最大连续子数组的和 转化为用整个数组的和 sum 减去 最小连续子数组的和! // dp[i] 表示以 i 位置为结尾的子数组和的最大值, sp[i] 表示以 i 位置为结尾的子数组和的最小值vector<int> dp(n + 1);auto sp = dp; // 和的最小值dp[0] = -INF, sp[0] = INF;int sum = 0;for(int i = 1; i <= n; i++){dp[i] = max(dp[i - 1] + nums[i - 1], nums[i - 1]);sp[i] = min(sp[i - 1] + nums[i - 1], nums[i - 1]);sum += nums[i - 1];}int max_dp = dp[1];int min_sp = sp[1];for(int i = 1; i <= n; i++){if(dp[i] > max_dp) max_dp = dp[i];if(sp[i] < min_sp) min_sp = sp[i];}// 当数组全部为负数的时候, sum 等于 sp[i],这种情况直接返回 max_dpreturn dp[i] == sum ? max_dp : max(max_dp, sum - min_sp);}
};

乘积最大数组

乘积最大子数组

class Solution {
public:int maxProduct(vector<int>& nums) {int n = nums.size();// 因为两个负数乘起来是一个正数,因此不能直接用 nums[i] * dp[i - 1] // 因此, 当 nums[i] 等于一个负数的时候, 需要乘一个最小乘积,才能得到最大的数// 所以, 还需要一个数组来记录前乘积最小的数组vector<int> f(n + 1);auto g = f;f[0] = 1, g[0] = 1;for(int i = 1; i <= n; i++){// 需要判断 nums[i] 的正负if(nums[i - 1] > 0) {f[i] = max(f[i - 1] * nums[i - 1], nums[i - 1]);g[i] = min(g[i - 1] * nums[i - 1], nums[i - 1]);}else{f[i] = max(g[i - 1] * nums[i  -1], nums[i - 1]);g[i] = min(f[i - 1] * nums[i - 1], nums[i - 1]);}}int ret = f[1];for(int i = 1; i <= n; i++) if(f[i] > ret) ret = f[i];return ret;}
};

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

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

相关文章

以题为例 浅谈sql注入二次注入

什么是二次注入 二次注入可以理解为&#xff0c;攻击者构造的恶意数据存储在数据库后&#xff0c;恶意数据被读取并进入到SQL查询语句所导致的注入。防御者即使对用户输入的恶意数据进行转义&#xff0c;当数据插入到数据库中时被处理的数据又被还原&#xff0c;Web程序调用存…

Linux/Validation

Enumeration nmap 第一次扫描发现系统对外开放了22&#xff0c;80&#xff0c;4566和8080端口&#xff0c;端口详细信息如下 系统对外开放了4个端口&#xff0c;从nmap的结果来看&#xff0c;8080无法访问&#xff0c;手动尝试后4566也无法访问&#xff0c;只能从80端口开始 …

机器视觉中应用正态分布

笔记来源—— 【工程数学基础】9_阈值如何选取&#xff1f;&#xff1f;在机器视觉中应用正态分布和6-Sigma【这是一期不需要记笔记的轻松视频&#xff0c;简单的知识&#xff0c;重要的运用】 比如我们要识别我们的产品上面是否有保护膜&#xff0c;我们可以通过白色像素点的…

c# combox 行间距调整

初始化combox comboBox1.DropDownStyle ComboBoxStyle.DropDownList;comboBox1.ItemHeight 25; // 设置 combox 的行高comboBox1.DrawMode DrawMode.OwnerDrawVariable; 添加 DrawItem 事件 private void comboBox1_DrawItem(object sender, DrawItemEventArgs e){if (…

二次封装 element-plus的Table 表格组件,减少代码臃肿

为什么要二次封装element-plus的Table 表格组件&#xff0c;言简意赅&#xff1a;以后难免会在表格里面加一些统一的逻辑&#xff0c;可以在表格里面书写重复的方法或样式 封装后的使用方式 props 参数类型可选值默认值说明tableDataArray——表格数据tableConfigArray——表…

OpenStack安装步骤

一、准备OpenStack安装环境 1、创建实验用的虚拟机实例。 内存建议16GB&#xff08;8GB也能运行&#xff09;CPU&#xff08;处理器&#xff09;双核且支持虚拟化硬盘容量不低于200GB&#xff08;&#xff01;&#xff09;网络用net桥接模式 运行虚拟机 2、禁用防火墙与SELin…

【CSP】2022-03-3 计算资源调度器 stl大模拟使用map优化索引 完整思路+完整的写代码过程(遇到的问题)+完整代码

2022-03-3 计算资源调度器 stl大模拟使用map优化索引 2022-03-3 计算资源调度器 stl大模拟使用map优化索引思路写代码的过程&#xff08;遇到的问题&#xff09;完整代码 2022-03-3 计算资源调度器 stl大模拟使用map优化索引 在联系了之前那么多道stl大模拟题后&#xff0c;终…

揭秘PostgreSQL:超越传统数据库的无限可能!

介绍&#xff1a;PostgreSQL是一个功能强大的开源对象关系数据库系统。以下是对PostgreSQL的详细介绍&#xff1a; 开源性&#xff1a;PostgreSQL是完全开源的&#xff0c;这意味着任何人都可以自由地获取、使用和修改它的源代码。 可定制性&#xff1a;它具有高度可定制性&…

问题解决:NPM 安装 TypeScript出现“sill IdealTree buildDeps”

一、原因&#xff1a; 使用了其他镜像&#xff08;例如我使用了淘宝镜像 npm config set registry https://registry.npm.taobao.org/ &#xff09; 二、解决方法&#xff1a; 1.切换为原镜像 npm config set registry https://registry.npmjs.org 安装typescript npm i …

前端开发的发展史:框架与技术栈的演变

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

告别“死记硬背”,坐席助手让客服新手秒变大咖

在客服行业&#xff0c;新手客服人员常常面临着两大难题&#xff1a;一是需要死记硬背大量的标准答案&#xff0c;二是培训时间长&#xff0c;上岗速度慢。然而&#xff0c;随着科技的发展&#xff0c;这些问题正逐渐得到。今天&#xff0c;我们要为大家介绍一款革命性的客服工…

STM32CubeIDE基础学习-STM32CubeIDE软件新增工程文件夹

STM32CubeIDE基础学习-STM32CubeIDE软件新增工程文件夹 文章目录 STM32CubeIDE基础学习-STM32CubeIDE软件新增工程文件夹前言第1章 添加文件夹第2章 添加文件路径2.1 相对路径方法2.2 绝对路径方法 总结 前言 在编程的过程中&#xff0c;如果需要在原有的工程基础上新增其它的…

哈希表|202.快乐数

力扣题目链接 int getSum(int n) {int sum 0;while (n) {sum (n % 10) * (n % 10);n / 10;}return sum; }bool isHappy(int n){int sum getSum(n);int hash[820] {0};while (sum ! 1) {if (hash[sum] 1) {return false;} else {hash[sum];}sum getSum(sum);}return true…

探索未来:2024年人工智慧驱动的 AI + 研发趋势

#2024 AI 辅助研发趋势# 当我们站在2024年的风口浪尖时&#xff0c;人工智慧辅助研发的格局即将发生翻天覆地的变化。2023年人工智慧的快速发展为各行业的突破性进步铺平了道路。从研发流程的数位转型&#xff0c;到 AI 开发工具2.0 的出现&#xff0c;未来充满了超越 Copilot…

基于数组的顺序表删除操作

删除算法需要注意&#xff1a; 1. 列表长度为0时不能再删除 2.每次删除后长度减一 3.输入删除的数据在原来列表中不存在&#xff0c;不需要改变原列表 #include <iostream> #define MAX 100; using namespace std;int search(int arr[],int len,int n) {for(int i0; i…

【2024泰迪杯】A 题:生产线的故障自动识别与人员配置 Python代码实现

【2024泰迪杯】A 题&#xff1a;生产线的故障自动识别与人员配置 Python代码实现 1 问题 一、问题背景 随着新兴信息技术的大规模应用&#xff0c;工业生产线的智能化控制技术日益成熟。自动生产线 可以自动完成物品传送、物料填装、产品包装和质量检测等过程&#xff0c;极…

LeetCode - 寻找数组的中心

先学习一下前缀和吧 LCR 012.寻找数组的中心LCR 012. 代码解析 在读题读到左侧元素之和等于右侧所有元素之和的时候&#xff0c;我觉得可以用前缀和&#xff0c;然后结合下面的示例&#xff0c;模拟了一下发现确实可以。 我的想法是搞两个数组&#xff0c;一个来存从左到右数…

微信小程序(五十六)逆地址解析示范

注释很详细&#xff0c;直接上代码 温馨提醒&#xff1a;记得给自己的key配额&#xff0c;基础操作与前提配置参考本专栏第五十四篇 新增内容&#xff1a; 1.逆地址解析基础示范 2.开放经纬度参数 3.只列举修改的js部分&#xff0c;前提配置请看 温馨提醒 源码&#xff1a; ind…

软件开发人员从0到1实现物联网项目:需求分析

文章目录 前言市场调研线下考察竞品参考 项目目标功能需求用户端功能需求商家功能需求系统管理功能需求 非功能需求性能安全性易用性扩展性可靠性 小结 前言 上文对实现自助棋牌室项目涉及到的技术做了调研&#xff0c;尤其是物联网技术。那接下来就是对需求进行一番分析了&am…

王道机试C++第 5 章 数据结构二:队列queue和21年蓝桥杯省赛选择题Day32

目录 5.2 队列 1&#xff0e;STL-queue 课上演示&#xff1a; 基本代码展示&#xff1a; 2. 队列的应用 例:约瑟夫问题 No. 2 题目描述&#xff1a; 思路提示&#xff1a; 代码展示&#xff1a; 例&#xff1a;猫狗收容所 题目描述&#xff1a; 代码表示&#xff1…