【算法深度探索】动态规划之旅(1):挑战OJ题海,解锁15道经典难题,让你成为DP大师!

在这里插入图片描述

📃博客主页: 小镇敲码人
🚀 欢迎关注:👍点赞 👂🏽留言 😍收藏
🌏 任尔江湖满血骨,我自踏雪寻梅香。 万千浮云遮碧月,独傲天下百坚强。 男儿应有龙腾志,盖世一意转洪荒。 莫使此生无痕度,终归人间一捧黄。🍎🍎🍎
❤️ 什么?你问我答案,少年你看,下一个十年又来了 💞 💞 💞

【算法深度探索】动态规划之旅(1):挑战OJ题海,解锁15道经典难题,让你成为DP大师!

  • OJ题1:石子游戏,难度分:1590
    • 题目解析
    • 算法原理
    • 代码实现
    • 使用滚动数组优化
  • OJ题2:下降路径最小和 难度分:1573
    • 题目解析
    • 算法原理
    • 代码实现
  • OJ题3:最长字符串链 难度分:1599
    • 题目解析
    • 算法原理
    • 代码实现
  • OJ题4:最长定差子序列 难度分:1597
    • 题目解析
    • 算法原理
    • 代码实现
  • OJ题5:将整数按权重排序 难度分:1507
    • 题目解析
    • 算法原理
    • 代码实现
  • OJ题6:使绳子变成彩色的最短时间 难度分:1574
    • 题目解析
    • 算法原理
    • 代码实现
  • OJ题7:统计字典序元音字符串的数目 难度分:1519
    • 题目解析
    • 算法原理
    • 代码实现
    • 滚动数组优化
  • OJ题8:子数组和的绝对值的最大值 难度分:1542
    • 题目解析
    • 算法原理
    • 代码实现
    • 滚动数组优化
  • OJ题9: 个位数字为 K 的整数之和 难度分:1559
    • 题目解析
    • 算法原理
    • 代码实现
  • OJ题10:达到末尾下标所需的最大跳跃次数 难度分:1533
    • 题目解析
    • 算法原理
    • 代码实现
  • OJ题11:判断是否能拆分数组 难度分:1543 ---区间dp
    • 题目解析
    • 算法原理
    • 代码实现
  • OJ题12:推多米诺 难度分:1638
    • 题目解析
    • 算法原理
    • 代码实现
  • OJ题13:将字符串翻转到单调递增 难度分:1602
    • 题目解析
    • 算法原理
    • 代码实现
    • 滚动数组优化
  • OJ题14:骑士拨号器 难度分:1690
    • 题目解析
    • 算法原理
    • 代码实现
    • 滚动数组优化
  • OJ题15:掷骰子等于目标和的方法数 难度分:1654---分组背包
    • 题目解析
    • 算法原理
    • 代码实现
    • 滚动数组优化

前言:本篇博客旨在帮助大家学习和了解DP算法,并熟练的掌握DP算法的原理和一些套路,以题解的形式给出,题目出自力扣平台,后面的数字代表难度分。

OJ题1:石子游戏,难度分:1590

这里是题目链接

题目解析

在这里插入图片描述

算法原理

下面我们来尝试使用动态规划来解决这道题。

在这里插入图片描述

代码实现

class Solution {
public:
    bool stoneGame(vector<int>& piles) {
    //创建dp表
    //初始化
    //填表
    //返回值
    int n = piles.size();
    vector<vector<int>> dp(n,vector<int>(n));
    dp[0][0] = piles[0];
    dp[n-1][n-1] = piles[n-1];

    for(int i = n-2;i >= 0;i--)
      for(int j = i;j < n;j++)
        if(j > 0)
          dp[i][j] = max(piles[i]-dp[i+1][j],piles[j]-dp[i][j-1]);
          
    return dp[0][n-1] > 0;
    }
};

ak截图:

在这里插入图片描述

使用滚动数组优化

在这里插入图片描述

代码实现:

class Solution {
public:
    bool stoneGame(vector<int>& piles) {
    //创建dp表
    //初始化
    //填表
    //返回值
    int n = piles.size();
    vector<int> dp(n);
    dp[0] = piles[0];
    dp[n-1] = piles[n-1];

    for(int i = n-2;i >= 0;i--)
      for(int j = i;j < n;j++)
        if(j > 0)
          dp[j] = max(piles[i]-dp[j],piles[j]-dp[j-1]);

    return dp[n-1] > 0;
    }
};

ak截图:

在这里插入图片描述

OJ题2:下降路径最小和 难度分:1573

这里是题目链接

题目解析

在这里插入图片描述

算法原理

我们尝试使用动态规划来解决一下这道题

在这里插入图片描述

代码实现

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& matrix) {
    //创建dp表
    //初始化
    //填表
    //返回值
    int INF = 0x3f3f3f3f;
    int n = matrix.size();
    int m = matrix[0].size();
    vector<vector<int>> dp(n+1,vector<int>(m+2,INF));
    for(int j = 0;j <= m;++j)
      dp[0][j] = 0;
      
    for(int i = 1;i <= n;++i)
      for(int j = 1;j <= m;++j)
        dp[i][j] = min(dp[i-1][j-1],min(dp[i-1][j],dp[i-1][j+1]))+matrix[i-1][j-1];
    
    int ret = INF;
    for(int j = 1;j <= m;++j)
       ret = min(ret,dp[n][j]);
    return ret;
    }
};

ak截图:

在这里插入图片描述

OJ题3:最长字符串链 难度分:1599

这里是题目链接

题目解析

在这里插入图片描述

算法原理

下面我们使用动态规划来解决一下这道题。

在这里插入图片描述

代码实现

int compare(string& a,string& b)
{
    return a.size() < b.size();
}
class Solution {
public:
    int longestStrChain(vector<string>& words) {
    sort(words.begin(),words.end(),compare);//排序
    unordered_map<string,int> hash;
    int n = words.size();
    for(int i = 0;i < n;++i)
      hash[words[i]] = i;
    
    vector<int> dp(n,1);
    
    int ret = 1;
    for(int i = 1;i < n;++i)
    {
        for(int j = 0;j < words[i].size();++j)
        {
            string wordprev = words[i].substr(0,j)+words[i].substr(j+1);
            if(hash.count(wordprev))
              dp[i] = max(dp[hash[wordprev]]+1,dp[i]);
        }
        ret = max(ret,dp[i]);
    }
    return ret;
    }
};

ak截图:

在这里插入图片描述

OJ题4:最长定差子序列 难度分:1597

这里是题目链接

题目解析

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

class Solution {
public:
    int longestSubsequence(vector<int>& arr, int difference) {
    int n = arr.size();
    unordered_map<int,int> hash;//值-下标
    //创建dp表
    //初始化
    //填表
    //返回值
    vector<int> dp(n,1);
    int ret = 0;
    for(int i = 0;i < n;++i)
    {
        int a = arr[i];
        if(hash.count(a-difference))
          dp[i] = dp[hash[a-difference]]+1;
        hash[arr[i]] = i;
        ret = max(ret,dp[i]);
    }
    return ret;
    }
};

ak截图:

在这里插入图片描述

OJ题5:将整数按权重排序 难度分:1507

这里是题目

题目解析

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

int compare(vector<int>& a,vector<int>& b)
{
    return a[1] < b[1] || (a[1] == b[1] && a[0] < b[0]);
}
class Solution {
private:
  unordered_map<int,int> dp;
public:
    int getF(int i)
    {
        if(dp.count(i))
          return dp[i];
        if(i == 1)
          return 0;
        else if(i & 1)
          return dp[i] = 1+getF(3*i+1);
        else
          return dp[i] = 1+getF(i/2);
    }
    int getKth(int lo, int hi, int k) {
    //创建dp表
    //初始化
    //填表
    vector<vector<int>> x;
    for(int i = lo;i <= hi;++i)
      x.push_back({i,getF(i)});
    sort(x.begin(),x.end(),compare);
    return x[k-1][0];
    }
};

ak截图:

在这里插入图片描述

OJ题6:使绳子变成彩色的最短时间 难度分:1574

使绳子变成彩色的最短时间

题目解析

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

class Solution {
public:
    int minCost(string colors, vector<int>& neededTime) {
    //创建dp表
    //初始化
    //填表
    //返回值
    int n = neededTime.size();
    vector<int> dp(n);
    int sum = 0;
    for(auto& i:neededTime)
      sum += i;
    dp[0] = neededTime[0];
    
    int ret = dp[0];
    int prev = 0;
    for(int i = 1;i < n;++i)
    {
      if(colors[i] != colors[i-1])
      {
        dp[i] = dp[i-1]+neededTime[i];
        prev = i;
      }
      else 
      {
         if(neededTime[i] > neededTime[prev])
         {
            dp[i] = dp[i-1]-neededTime[prev]+neededTime[i];
            prev = i;
         }
         else
           dp[i] = dp[i-1];
      }
        ret = max(ret,dp[i]);
    }
      return sum-ret;
    }
};

ak截图:

在这里插入图片描述

OJ题7:统计字典序元音字符串的数目 难度分:1519

这里是题目

题目解析

在这里插入图片描述

算法原理

下面我们使用动态规划来解决一下这道题。

在这里插入图片描述

代码实现

class Solution {
public:
    int countVowelStrings(int n) {
    //创建dp表
    //初始化
    //填表
    //返回值
    vector<vector<int>> dp(n+1,vector<int>(6));
    dp[0][5] = 1;
    for(int i = 1;i <= n;++i)
      for(int j = 1;j <= 5;++j)
        {
            for(int k = j;k <= 5;++k)
              dp[i][j] += dp[i-1][k];
        }
    
    int ret = 0;
    for(int i = 1;i <= 5;++i)
      ret += dp[n][i];
    return ret;
    }
};

ak截图:

在这里插入图片描述

滚动数组优化

很明显,每一个状态只依赖于它自己和它上一行后面列的数,只用一维数组实现滚动就可以了,注意要从左向右滚动,否则我们要的数就会被覆盖。

代码实现:

class Solution {
public:
    int countVowelStrings(int n) {
    //创建dp表
    //初始化
    //填表
    //返回值
    vector<int> dp(6);
    dp[5] = 1;
    for(int i = 1;i <= n;++i)
      for(int j = 1;j <= 5;++j)
        {
            for(int k = j+1;k <= 5;++k)
              dp[j] += dp[k];
        }
    
    int ret = 0;
    for(int i = 1;i <= 5;++i)
      ret += dp[i];
    return ret;
    }
};

ak截图:

在这里插入图片描述

OJ题8:子数组和的绝对值的最大值 难度分:1542

这里是题目

题目解析

在这里插入图片描述

算法原理

下面我们使用动态规划来解决一下这道题。

在这里插入图片描述

代码实现

class Solution {
public:
    int maxAbsoluteSum(vector<int>& nums) {
    //创建dp表
    //初始化
    //填表
    //返回值
    int n = nums.size();
    vector<int> f(n),g(n);
    g[0] = f[0] = nums[0];
    int ret = abs(nums[0]);

    for(int i = 1;i < n;++i)
    {
        f[i] = max(f[i-1]+nums[i],nums[i]);
        g[i] = min(g[i-1]+nums[i],nums[i]);
        ret = max(ret,max(f[i],abs(g[i])));
    }
    return ret;
    }
};

ak截图:

在这里插入图片描述

滚动数组优化

我们可以发现不管是g数组、还是f数组它每一次推导之前那个状态都只依赖于前一个状态,我们可以使用两个变量来取代那一个数组,不断让新的值覆盖这个变量即可,保证要用到上一个状态的时候它还没有被覆盖,所以要从左往右填表。

代码实现:

class Solution {
public:
    int maxAbsoluteSum(vector<int>& nums) {
    //创建dp表
    //初始化
    //填表
    //返回值
    int n = nums.size();
    int g = nums[0],f = nums[0];
    int ret = abs(nums[0]);

    for(int i = 1;i < n;++i)
    {
        f = max(f+nums[i],nums[i]);
        g = min(g+nums[i],nums[i]);
        ret = max(ret,max(f,abs(g)));
    }
    return ret;
    }
};

ak截图:

在这里插入图片描述

OJ题9: 个位数字为 K 的整数之和 难度分:1559

这里是题目

题目解析

在这里插入图片描述

算法原理

在这里插入图片描述

代码实现

class Solution {
public:
    int minimumNumbers(int num, int k) {
    //创建dp表
    //初始化
    //返回值
    vector<int> dp(num+1,INT_MAX);
    vector<int> ans;//保存个位为k的数
    dp[0] = 0;
    for(int i = 1;i <= num;++i)
    {
        if(i % 10 == k)
          dp[i] = 1;
        else
        {
            for(int j = 0;j < ans.size();++j)
            {
                if(dp[i-ans[j]] != INT_MAX)
                  dp[i] = min(dp[i],dp[i-ans[j]]+1);
            }
        }
        if(i % 10 == k)
          ans.push_back(i);
    }
    return dp[num] == INT_MAX ? -1:dp[num];
    }
};

ak截图:

在这里插入图片描述

OJ题10:达到末尾下标所需的最大跳跃次数 难度分:1533

这里是题目

题目解析

在这里插入图片描述

算法原理

我们来尝试使用动态规划来解决这个题目。

在这里插入图片描述

代码实现

class Solution {
public:
    int maximumJumps(vector<int>& nums, int target) {
    //创建dp表
    //初始化
    //返回值
    int n = nums.size();
    vector<int> dp(n,INT_MIN);
    dp[0] = 0;
    for(int i = 1;i < n;++i)
    {
        for(int j = i-1;j >= 0;--j)
        {
            int gap = abs(nums[j]-nums[i]);
            if(gap <= target && dp[j] != INT_MIN)
            {
                dp[i] = max(dp[j]+1,dp[i]);
            }
        }
    }
    return dp[n-1] == INT_MIN ? -1 : dp[n-1];
    }
};

ak截图:

在这里插入图片描述

OJ题11:判断是否能拆分数组 难度分:1543 —区间dp

这里是题目

题目解析

在这里插入图片描述

算法原理

下面我们尝试使用动态规划来解决一下这道题。

在这里插入图片描述

代码实现

class Solution {
public:
    bool canSplitArray(vector<int>& nums, int m) {
    //创建dp表
    //初始化
    //返回值
    int n = nums.size();
    vector<vector<bool>> dp(n,vector<bool>(n,true));
    for(int i = 0;i+3 <= n;++i)
    {
        if(nums[i]+nums[i+1] >= m || nums[i+1]+nums[i+2] >= m)
          dp[i][i+2] = true;
        else
          dp[i][i+2] = false; 
    }

    for(int i = n-2;i >= 0;--i)
    {
        for(int j = i+3;j < n;++j)
          dp[i][j] = dp[i+1][j] || dp[i][j-1];
    }
    
    return dp[0][n-1];
    }
};

ak截图:

在这里插入图片描述

OJ题12:推多米诺 难度分:1638

这里是题目

题目解析

在这里插入图片描述

算法原理

下面我们使用动态规划来解决一下这道题。

在这里插入图片描述

代码实现

class Solution {
public:
    string pushDominoes(string& dominoes) {
    //创建dp表
    //初始化
    int n = dominoes.size();
    vector<int> dp(n,0);
    if(dominoes[0] == 'L')
      dp[0] = -1;
    if(dominoes[0] == 'R')
      dp[0] = 1;
    for(int i = 1;i < n;++i)
    {
        if(dominoes[i] == '.')
        {
            if(dp[i-1] > 0)
              dp[i] = dp[i-1]+1;
        }
        else if(dominoes[i] == 'R')
          dp[i] = 1;
        else
         dp[i] = -1;
    }


    for(int i = n-1;i >= 0;--i)
    {
      if(dominoes[i] == '.')
      {
        if(i < n-1 && dp[i+1] < 0)
        {
            if(dp[i] + dp[i+1]-1 > 0)
              dp[i] = dp[i+1]-1;
            else if(dp[i]+dp[i+1]-1 == 0)
              dp[i] = 0;
            else if(dp[i] <= 0)
              dp[i] = dp[i+1]-1;
        }
        if(dp[i] == 0)
          dominoes[i] = '.';
        else if(dp[i] > 0)
          dominoes[i] = 'R';
        else 
          dominoes[i] = 'L';
      }
      
    }

    return dominoes;
    }
};

ak截图:

在这里插入图片描述

OJ题13:将字符串翻转到单调递增 难度分:1602

这里是题目

题目解析

在这里插入图片描述

算法原理

我们使用动态规划来解决一下这道题。

在这里插入图片描述

代码实现

class Solution {
public:
    int minFlipsMonoIncr(string s) {
    //创建dp表
    //初始化
    //填表
    //返回值
    int n = s.size();
    vector<vector<int>> dp(n+1,vector<int>(2));
    for(int i = 2;i <= n;++i)
    {
       if(s[i-1] == '0')
       {
          dp[i][0] = dp[i-1][0];
          if(s[i-2] != '0')
            dp[i][0]++;
          dp[i][1] = min(dp[i-1][0],dp[i-1][1])+1;
       }
       else//s[i-1] == '1'
       {
        dp[i][0] = dp[i-1][0];
        if(s[i-2] != '0')
            dp[i][0]++;
          dp[i][1] = min(dp[i-1][0],dp[i-1][1]);
       } 
    }
    return min(dp[n][1],dp[n][0]);
    }
};

ak截图:

在这里插入图片描述

滚动数组优化

0和1状态只依赖之前的一个状态,我们可以使用滚动数组优化。

代码实现:

class Solution {
public:
    int minFlipsMonoIncr(string s) {
    //创建dp表
    //初始化
    //填表
    //返回值
    int n = s.size();
    vector<int> dp(2);
    for(int i = 2;i <= n;++i)
    {
       if(s[i-1] == '0')
       {
          dp[1] = min(dp[0],dp[1])+1;
          if(s[i-2] != '0')
               dp[0]++;
       }
       else//s[i-1] == '1'
       {

        dp[1] = min(dp[0],dp[1]);
         if(s[i-2] != '0')
             dp[0]++; 
}
       
    }
    return min(dp[1],dp[0]);
    }
};

这里注意初始化顺序,保证我们用到之前那个状态时它还没被覆盖即可。

ak截图:

在这里插入图片描述

OJ题14:骑士拨号器 难度分:1690

这里是题目

题目解析

算法原理

下面我们使用动态规划来解决一下这道题。

在这里插入图片描述

代码实现

class Solution {
public:
    int knightDialer(int n) {
    //创建dp表
    //初始化
    //填表
    //返回值
    const int MOD = 1e9+7;
    vector<vector<long long>> dp(n+1,vector<long long>(12,0));
    for(int j = 0;j < 12;++j)
      dp[1][j] = 1;
    
    for(int i = 2;i <= n;++i)
      for(int j = 1;j < 12;++j)
      {
         switch(j)
         {
            case 1:dp[i][j] = (dp[i-1][6]+dp[i-1][8])%MOD;
            break;
            case 2:dp[i][j] =  (dp[i-1][9]+dp[i-1][7])%MOD;
            break;
             case 3:dp[i][j] =  (dp[i-1][4]+dp[i-1][8])%MOD;
            break;
             case 4:dp[i][j] =  (dp[i-1][11]+dp[i-1][3]+dp[i-1][9])%MOD;
            break;
             case 6:dp[i][j] =  (dp[i-1][11]+dp[i-1][1]+dp[i-1][7])%MOD;
            break;
             case 7:dp[i][j] =  (dp[i-1][2]+dp[i-1][6])%MOD;
            break;
             case 8:dp[i][j] =  (dp[i-1][1]+dp[i-1][3])%MOD;
            break;
             case 9:dp[i][j] =  (dp[i-1][2]+dp[i-1][4])%MOD;
            break;
             case 11:dp[i][j] =  (dp[i-1][6]+dp[i-1][4])%MOD;
            break;
            default:
            break;
         }
      }
    long long ret = 0;
    for(int j = 1;j < 12;++j)
    {
        if(j != 10)
            ret += dp[n][j];
    }
    return ret%MOD;
    }
};

ak截图:

在这里插入图片描述

滚动数组优化

这里虽然我们当前行的状态可能会互相用不同列的状态,我们开一个新的数组把原来的数组的值保存一下还是可以使用达到空间优化的效果。

代码实现:

class Solution {
public:
    int knightDialer(int n) {
    //创建dp表
    //初始化
    //填表
    //返回值
    if(n == 1)
      return 10;
    const int MOD = 1e9+7;
    vector<int> dp(12,0);
    for(int j = 0;j < 12;++j)
      dp[j] = 1;
    
    for(int i = 2;i <= n;++i)
    {
      vector<int> dp1(dp);
      for(int j = 1;j < 12;++j)
      {
         switch(j)
         {
            case 1:dp[j] = (dp1[6]+dp1[8])%MOD;
            break;
            case 2:dp[j] =  (dp1[9]+dp1[7])%MOD;
            break;
             case 3:dp[j] =  (dp1[4]+dp1[8])%MOD;
            break;
             case 4:dp[j] =  (0LL+dp1[11]+dp1[3]+dp1[9])%MOD;
            break;
             case 6:dp[j] =  (0LL+dp1[11]+dp1[1]+dp1[7])%MOD;
            break;
             case 7:dp[j] =  (dp1[2]+dp1[6])%MOD;
            break;
             case 8:dp[j] =  (dp1[1]+dp1[3])%MOD;
            break;
             case 9:dp[j] =  (dp1[2]+dp1[4])%MOD;
            break;
             case 11:dp[j] =  (dp1[6]+dp1[4])%MOD;
            break;
            default:
            break;
         }
      }
    }
    long long ret = 0;
    for(int j = 1;j < 12;++j)
    {
        if(j != 10 && j != 5)
            ret += dp[j];
    }
    return ret%MOD;
    }
};
  • 注意:我们的中间结果可能溢出,我们在加法的前面加上0LL(long long类型的0),就可以把int类型加法转化为long long类型的加法,然后模上一个值,int就不会溢出了。

ak截图:

在这里插入图片描述

也可以使用状态机来求解,优化的关键是要找出数字之间的对称关系已达到状态压缩的目的,把图画好,可以参考这篇题解

OJ题15:掷骰子等于目标和的方法数 难度分:1654—分组背包

这里是题目

题目解析

在这里插入图片描述

算法原理

下面我们使用动态规划来解决一下这道题。

在这里插入图片描述

代码实现

class Solution {
public:
    int numRollsToTarget(int n, int k, int target) {
    //创建dp表
    //初始化
    //填表
    //返回值
    const int MOD = 1e9+7;
    vector<vector<int>> dp(n+1,vector<int>(target+1));
    dp[0][0] = 1;

    for(int i = 1;i <= n;++i)
      for(int j = 1;j <= target;++j)
        for(int x = 1;x <= k;++x)
        {
            if(j-x >= 0)
              dp[i][j] = (0LL+dp[i][j]+dp[i-1][j-x])%MOD;
        }
    return dp[n][target];
    }
};

ak截图:

在这里插入图片描述

滚动数组优化

我们观察到,dp[i][j]所依赖的状态都是j比它小的值,所以我们第二维倒着遍历,保证我们用到这个状态的时候,它还没有被更新为最新一行的值,注意每一个j状态更新前都要将其赋值为0,因为上一行的值对我们这行已经不起作用了。

代码实现:

class Solution {
public:
    int numRollsToTarget(int n, int k, int target) {
    //创建dp表
    //初始化
    //填表
    //返回值
    const int MOD = 1e9+7;
    vector<int> dp(target+1);
    dp[0] = 1;

    for(int i = 1;i <= n;++i)
      for(int j = target;j >= 0;--j)
      {
        dp[j] = 0;
        for(int x = 1;x <= k;++x)
        {
            if(j-x >= 0)
            {
                 dp[j] = (0LL+dp[j]+dp[j-x])%MOD;
            }
        }
      }
    return dp[target];
    }
};

ak截图:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uniapp小程序下载并导出excel

<button click"confirmExport">导出excel</button>confirmExport() {let header {"X-Access-Token": uni.getStorageSync(ACCESS_TOKEN), //自定义请求头信息} let url "http"/......"; // 后端API地址uni.request({url: ur…

Java(多线程)

一、基本概念 进程&#xff1a;一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元&#xff0c;在传统的操作系统中&#xff0c;进程既是基本的分配单元&#xff0c;也是基本的执行单元。线程&#xff1a;操作系统中能够进行运算的最…

比较好玩的车子 高尔夫6

https://www.sohu.com/a/484063087_221273 四万多如愿收获手动挡高尔夫6&#xff0c;可靠性、经济性、操控性兼顾_搜狐汽车_搜狐网 2.基本上其他人也不知道到底是什么相关的车子信息

【算法刷题】八大排序算法总结(冒泡、选择、插入、二分插入、归并、快速、希尔、堆排序)

文章目录 八大排序算法总结1.冒泡排序2.选择排序3.插入排序4.二分插入排序5.归并排序6.快速排序7.希尔排序8.堆排序 八大排序算法总结 排序排序方法平均情况最好情况最坏情况空间稳定性1冒泡排序O(n2)O(n)O(n2)O(1)稳定2选择排序O(n2)O(n2)O(n2)O(1)不稳定3插入排序O(n2)O(n)O…

java io模型

一、五种IO模型 在《Unix网络编程》一书中提到了五种IO模型&#xff0c;分别是&#xff1a;阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO。 而Reactor模式实现了同步非阻塞模型&#xff0c;而Proactor模式实现了异步非阻塞模型 具体方面请参考我的另一篇博客 网络io…

Spring Validation解决后端表单校验

NotNull&#xff1a;从前台传递过来的参数不能为null,如果为空&#xff0c;会在控制台日志中把message打印出来 Range&#xff1a;范围&#xff0c;最大多少&#xff0c;最小多少 Patten&#xff0c;标注的字段值必须符合定义的正则表达式&#xff08;按照业务规则&#xff0…

车队试验的远程实时显示方案

风丘科技推出的数据远程实时显示方案更好地满足了客户对于试验车队远程实时监控的需求&#xff0c;并真正实现了试验车队的远程管理。随着新的数据记录仪软件IPEmotion RT和相应的跨平台显示解决方案的引入&#xff0c;让我们的客户端不仅可在线访问记录器系统状态&#xff0c;…

Go语言中的互斥锁(Mutex)和读写锁(RWMutex)

Mutex Mutex结构体 type Mutex struct {state int32 //表示互斥锁的状态,比如是否被锁定等sema uint32 //表示信号里,协程阻塞等待的信号量,解锁的协程释放信号量从而唤醒等待信号量的协程 } Locked: 表示Mutex是否已被锁定(1表示已经被锁定)Woken: 表示是否有协程被唤醒(1已有…

达梦的归档日志参数ARCH_RESERVE_TIME测试

达梦的参数ARCH_RESERVE_TIME测试 前面有提到和oracle相比&#xff0c;达梦的归档日志相关参数有个比较特别&#xff0c;可以通过设置它去规定归档日志的保留时间。 ARCH_RESERVE_TIME&#xff1a;归档日志保留时间&#xff0c;单位分钟&#xff0c;取值范围 0~2147483647。只…

Angular 使用DomSanitizer

跨站脚本Cross-site scripting 简称XSS&#xff0c;是代码注入的一种&#xff0c;是一种网站应用程序的安全漏洞攻击。它允许恶意用户将代码注入到网页上&#xff0c;其他用户在使用网页时就会收到影响&#xff0c;这类攻击通常包含了HTML和用户端脚本语言&#xff08;JS&…

Word中图表题注样式自动编号

需求 在写论文的时候&#xff0c;希望图表题注是下面的样子&#xff0c;其中图号表示为&#xff1a;章的编号-本章中图的序号&#xff0c;而且都是小写数字。 网上找的方法大多是使用 “插入题注” 来插入&#xff0c;此时章的编号是大写的&#xff0c;如“图一-1”。然后再通…

什么是Rust?

Rust is a programming language focused on safety, particularly safe concurrency, supporting functional and imperative-procedural paradigms. Rust is syntactically similar to C, but it provides memory safety without using garbage collection. Rust是一种专注于…

[大模型]ChatGLM3-6B Transformers部署调用

ChatGLM3-6B Transformers部署调用 环境准备 在autodl平台中租一个3090等24G显存的显卡机器&#xff0c;如下图所示镜像选择PyTorch–>2.0.0–>3.8(ubuntu20.04)–>11.8 接下来打开刚刚租用服务器的JupyterLab&#xff0c;并且打开其中的终端开始环境配置、模型下载…

在 Python 中使用 Turtle 绘制火影忍者

火影忍者是一个流行的动漫角色&#xff0c;它是最受欢迎的动漫之一&#xff0c;下面的代码将向您展示如何使用 python Turtle 绘制火影忍者。 import turtle turtle.Screen().bgcolor("#eeeeee") draw turtle.Turtle() draw.pencolor("red") draw.pensi…

FPGA:图像数字细节增强算法(工程+仿真+实物,可用毕设)

目录 日常唠嗑一、视频效果二、硬件及功能1、硬件选择2、功能3、特点 未完、待续……四、工程设计五、板级验证六、工程获取 日常唠嗑 有2个多月没写文章了&#xff0c;又是老借口&#xff1a;“最近实在是很忙”&#x1f923;&#xff0c;不过说真&#xff0c;确实是比较忙&am…

Spring与Spring Boot的区别:从框架设计到应用开发

这是我自己开发的一款小程序&#xff0c;感兴趣的可以体验一下&#xff1a; 进入正题&#xff1a; 在Java开发领域&#xff0c;Spring和Spring Boot都是备受推崇的框架&#xff0c;它们为开发人员提供了丰富的功能和便捷的开发体验。然而&#xff0c;许多人对它们之间的区别仍…

【状态机dp】【 排序 】 2809使数组和小于等于 x 的最少时间

本文涉及知识点 【状态机dp】 排序 LeetCode 2809. 使数组和小于等于 x 的最少时间 给你两个长度相等下标从 0 开始的整数数组 nums1 和 nums2 。每一秒&#xff0c;对于所有下标 0 < i < nums1.length &#xff0c;nums1[i] 的值都增加 nums2[i] 。操作 完成后 &…

MySQL-多表查询:多表查询分类、SQL99语法实现多表查询、UNION的使用、7种SQL JOINS的实现、SQL99语法新特性、多表查询SQL练习

多表查询 1. 一个案例引发的多表连接1.1 案例说明1.2 笛卡尔积&#xff08;或交叉连接&#xff09;的理解1.3 案例分析与问题解决 2. 多表查询分类讲解分类1&#xff1a;等值连接 vs 非等值连接等值连接非等值连接 分类2&#xff1a;自连接 vs 非自连接分类3&#xff1a;内连接…

结构型模式--3.组合模式【草帽大船团】

1. 好大一棵树 路飞在德雷斯罗萨打败多弗朗明哥之后&#xff0c;一些被路飞解救的海贼团自愿加入路飞麾下&#xff0c;自此组成了草帽大船团&#xff0c;旗下有7为船长&#xff0c;分别是&#xff1a; 俊美海贼团75人 巴托俱乐部56人 八宝水军1000人 艾迪欧海贼团4人 咚塔塔海…

Leetcode223. 矩形面积

Every day a Leetcode 题目来源&#xff1a;223. 矩形面积 解法1&#xff1a;数学 两个矩形覆盖的总面积等于两个矩形的面积之和减去两个矩形的重叠部分的面积。由于两个矩形的左下顶点和右上顶点已知&#xff0c;因此两个矩形的面积可以直接计算。如果两个矩形重叠&#xf…