Day44——Dp专题

news2024/11/19 19:26:44

文章目录

    • 子序列问题
      • 27.最长递增子序列
      • 28、最长连续递增序列
      • 29、最长重复子数组
      • 30、最长公共子序列
      • 31、不相交的线
      • 32、最大子序和
      • 33、判断子序列
      • 34、不同的子序列
      • 35、两个字符串的删除操作
      • 36、编辑距离
      • 37、回文子串
      • 38、最长回文子序列
    • 动态规划总结篇
      • 背包问题系列
      • 股票系列
      • 子序列系列


子序列问题

27.最长递增子序列

力扣题目链接

状态表示:dp[i]:包含i的前i之前的以nums[i]结尾的最长上升子序列长度

状态计算:由于是不连续的,我们考虑最后一个,要计算dp[i]就要全部考虑nums[0 ~ i-1]即 j来枚举nums[0~i-1]

if(nums[i] > nums[j])

dp[i] = max(dp[i], dp[j] + 1)

动规五部曲

  • 确定dp数组以及下标的含义

dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度

  • 确定递推公式

if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);

注意这里不是要dp[i] 与 dp[j] + 1进行比较,而是我们要取dp[j] + 1的最大值。

  for(int i = 0;i < n;i++){
            for(int j = 0;j < i;j++){
                if(nums[i] > nums[j]){
                    dp[i] = Math.max(dp[i],dp[j]+1);
                }
            }
  • dp数组初始化

每一个i,对应的dp[i](即最长递增子序列)起始大小至少都是1。

 Arrays.fill(dp,1);
  • 确定遍历顺序

那么遍历i,j一定是从前向后遍历

  • 打印并举例推导dp数组

image-20221223185110498

Code

class Solution {
    public int lengthOfLIS(int[] nums) {
        int[] dp = new int[nums.length];
        int n = nums.length;
        Arrays.fill(dp,1);
        int res = 1;
        for(int i = 0;i < n;i++){
            for(int j = 0;j < i;j++){
                if(nums[i] > nums[j]){
                    dp[i] = Math.max(dp[i],dp[j]+1);
                }
            }
        res = Math.max(res,dp[i]);
        }
        return res;
    }
}

28、最长连续递增序列

力扣题目链接

状态表示:dp[i]:表示包含i的以nums[i]结尾的最长连续递增序列的长度为dp[i]

由于是连续的我们就只要比较相邻前后两个元素与i-1比较即可,不用像不连续的最长递增子序列那样与j : 0~i-1上的数进行比较

动规五部曲

  • 确定dp数组以及下标的含义

dp[i]:以下标i为结尾的连续递增的子序列长度为dp[i]。

  • 确定递推公式

如果 nums[i] > nums[i - 1],那么以 i 为结尾的连续递增的子序列长度 一定等于以i - 1为结尾的连续递增的子序列长度 + 1 。

即:dp[i] = dp[i - 1] + 1;

 for(int i = 1;i < n;i++){
     if(nums[i] > nums[i-1]){
        dp[i] = Math.max(dp[i],dp[i-1]+1);
      }
     res = Math.max(res,dp[i]);
 }
  • dp数组初始化

从前向后遍历,因为只需要与前一个进行比较,所以dp数组都初始化1

 Arrays.fill(dp,1);
  • 确定遍历顺序

所以一定是从前向后遍历。

  • 举例并推导dp数组

image-20221223192831095

Code

class Solution {
    public int findLengthOfLCIS(int[] nums) {
        int[] dp = new int[nums.length];
        int n = nums.length;
        Arrays.fill(dp,1);
        int res = 1;
        for(int i = 1;i < n;i++){
            if(nums[i] > nums[i-1]){
                dp[i] = Math.max(dp[i],dp[i-1]+1);
            }
            res = Math.max(res,dp[i]);
        }
        return res;
    }
}

29、最长重复子数组

力扣题目链接

状态表示:f[i][j]:nums1[0~i-1]以nums1[i - 1]结尾的和nums2[0~j-1]以nums2[j - 1]结尾的最长重复子数组长度为f[i][j]

属性:Max_count

初始化:

根据dp[i][j]的定义,dp[i][0] 和dp[0][j]其实都是没有意义的!(-1怎么结尾呢是吧)

dp[i][0] dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;

所以dp[i][0] 和dp[0][j]初始化为0

动态规划五部曲:

  • 确定dp数组以及下标的含义

dp[i][j] :以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度为dp[i][j]。 (特别注意: “以下标i - 1为结尾的A” 标明一定是 以A[i-1]为结尾的字符串 )

  • 确定递推公式

根据dp[i][j]的定义,dp[i][j]的状态只能由dp[i - 1][j - 1]推导出来。

即当A[i - 1] 和B[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1;

for(int i = 1;i < n;i++){
for(int j = 1;j < m;j++){
    if(nums1[i-1] == nums2[j-1]){
       dp[i][j] = Math.max(dp[i][j],dp[i-1][j-1]+1);
                }
    res = Math.max(dp[i][j],res);
	}
}
  • dp数组如何初始化

dp[i][0] 和dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;

所以dp[i][0] 和dp[0][j]初始化为0。

  • 确定遍历顺序

所以一定是从前向后遍历。

  • 举例推导dp数组

image-20221223201859533

Code

class Solution {
    public int findLength(int[] nums1, int[] nums2) {
        int[][] dp = new int[nums1.length+1][nums2.length+1];
        int n = nums1.length + 1;
        int m = nums2.length + 1;
        int res = 0;
        for(int i = 1;i < n;i++){
            for(int j = 1;j < m;j++){
                if(nums1[i-1] == nums2[j-1]){
                    dp[i][j] = Math.max(dp[i][j],dp[i-1][j-1]+1);
                }
                res = Math.max(dp[i][j],res);
            }
        }
        return res;
    }
}

30、最长公共子序列

力扣题目链接

四种基本状态

dp[i-1][j-1]

dp[i][j-1]

dp[i-1][j]

dp[i][j]

1.确定dp数组(dp table)以及下标的含义

dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]

2.确定递推公式

text1[i - 1] 与 text2[j - 1]相同,text1[i - 1] 与 text2[j - 1]不相同

如果text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;

如果text1[i - 1] 与 text2[j - 1]不相同,那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。

即:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);

if(char1 == char2){
    dp[i][j] = dp[i-1][j-1] + 1;
}
else{
    dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
}

3.dp数组如何初始化

dp[i][0] = 0;

dp[0][j]也是0。

4.确定遍历顺序

image-20221223210201175

5.举例推导dp数组

Code

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        int[][] dp = new int[text1.length()+1][text2.length()+1];
        int n = text1.length()+1;
        int m = text2.length()+1;
        int res = 0;
        for(int i = 1;i < n;i++){
            for(int j = 1;j < m;j++){
                char char1 = text1.charAt(i-1);
                char char2 = text2.charAt(j-1);
                if(char1 == char2){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }
                else{
                    dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
                }
                res = Math.max(res,dp[i][j]);
            }
        }
        return res;
    }
}

31、不相交的线

力扣题目链接

要求相等且不相交且要最长的———— 其实就是最长公共子序列!

Code

class Solution {
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        int n = nums1.length;
        int m = nums2.length;
        int res = 0;
        int[][] dp = new int[n+1][m+1];
        for(int i = 1;i < n + 1;i++){
            for(int j = 1;j < m + 1;j++){
                if(nums1[i - 1] == nums2[j - 1]){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }
                else{
                    dp[i][j] = Math.max(dp[i][j-1],dp[i-1][j]);
                }
                res = Math.max(res,dp[i][j]);
            }
        }
        return dp[n][m];
    }
}

32、最大子序和

力扣题目链接

状态表示dp[i]:表示以nums[i]结尾的最大连续子段和,dp[i]只与dp[i - 1]有关

属性:Max

假设数组 nums 的值全都严格大于 0,那么一定有 dp[i] = dp[i - 1] + nums[i]

状态转移:但由于存在负数的情况,因此要分类讨论:

  • dp[i - 1] <= 0,那么dp[i]要是加上它反而变小了,为此dp[i] = nums[i]
  • dp[i - 1] > 0,那么 dp[i] = dp[i - 1] + nums[i]
  • 初始化:f[0] = nums[0],以nums[0]结尾的和即为它本身。

动规五部曲

  • 确定dp数组以及其下标的含义

dp[i]表示以nums[i]结尾的最大连续子段和

  • 确定递推公式

dp[i]只有两个方向可以推出来:

  • dp[i - 1] + nums[i],即:nums[i]加入当前连续子序列和

  • nums[i],即:从头开始计算当前连续子序列和

  • dp数组初始化

dp[0]应为nums[0]即dp[0] = nums[0]。

  • 确定遍历顺序

递推公式中dp[i]依赖于dp[i - 1]的状态,需要从前向后遍历。

  • 举例并推导dp数组

image-20221224125510584

那么我们要找最大的连续子序列,就应该找每一个i为终点的连续最大子序列。

所以在递推公式的时候,可以直接选出最大的dp[i]。

Code

class Solution {
    public int maxSubArray(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        dp[0] = nums[0];
        int res = nums[0];
        for(int i = 1;i < n;i++){
            dp[i] = Math.max(dp[i-1]+nums[i],nums[i]);
            res = Math.max(res,dp[i]);
        }
        return res;
    }
}

33、判断子序列

力扣题目链接

状态计算:

  • if (s[i] == t[j ]),那么dp[i][j] = dp[i - 1][j - 1] + 1;,因为找到了一个相同的字符,相同子序列长度自然要在dp[i-1][j-1]的基础上加1
  • if (s[i ] != t[j]),此时相当于t要删除元素,t如果把当前元素t[j ]删除,使得s[1~i]与t[1 ~ j-1]相匹配!即dp[i][j] = dp[i][j - 1];
  if(char1 == char2){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }else{
                    dp[i][j] = dp[i][j-1];
                }

动规五部曲

  • 确定dp数组以及下标的含义

dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度为dp[i][j]

  • 确定递推公式

if (s[i - 1] == t[j - 1]),dp[i][j] = dp[i - 1][j - 1] + 1;

if (s[i - 1] != t[j - 1]),dp[i][j] = dp[i][j - 1];

  • dp数组初始化

``dp[i][j]都是依赖于dp[i - 1][j - 1] 和 dp[i][j - 1],所以dp[0][0]和dp[i][0]`都要初始化

  • 确定遍历顺序

image-20221224132848544

  • 举例并推导dp数组

dp[i][j]表示以下标i-1为结尾的字符串s和以下标j-1为结尾的字符串t 相同子序列的长度,所以如果dp[s.size()][t.size()] 与 字符串s的长度相同说明:s与t的最长相同子序列就是s,那么s 就是 t 的子序列。

  if(res == n){
            return true;
        }else{
            return false;
        }

Code

class Solution {
    public boolean isSubsequence(String s, String t) {
        int n = s.length();
        int m = t.length();
        int[][] dp = new int[n+1][m+1];
        int res = 0;
        for(int i = 1;i < n + 1;i++){
            for(int j = 1;j < m + 1;j++){
                char char1 = s.charAt(i-1);
                char char2 = t.charAt(j-1);
                if(char1 == char2){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }else{
                    dp[i][j] = dp[i][j-1];
                }
                res = Math.max(res,dp[i][j]);
            }
        }
        if(res == n){
            return true;
        }else{
            return false;
        }
    }
}

34、不同的子序列

力扣题目链接

image-20221224145309217

动规五部曲

  • 确定dp数组以及其下标的含义

dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]

  • 确定递推公式

  • s[i - 1] 与 t[j - 1]相等

    • 用s[i - 1]来匹配,个数为dp[i - 1][j - 1]
    • 不用s[i - 1]来匹配,个数为dp[i - 1][j]
  • s[i - 1] 与 t[j - 1] 不相等

    • 个数为dp[i - 1][j]
  if(s.charAt(i - 1) == t.charAt(j - 1)){
                    dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
                }else{
                    dp[i][j] = dp[i - 1][j];
                }
  • dp数组初始化

dp[i][0]应初始化为1,其余初始化为0

  • 确定遍历顺序

从递推公式dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]; 和 dp[i][j] = dp[i - 1][j]; 中可以看出dp[i][j]都是根据左上方和正上方推出来的。

所以遍历的时候一定是从上到下,从左到右

  • 举例并推导dp数组

image-20221224145733382

Code

class Solution {
    public int numDistinct(String s, String t) {
        int n = s.length();
        int m = t.length();
        int[][] dp = new int[n+1][m+1];
        for(int i = 0;i < n + 1;i++){
            dp[i][0] = 1;
        }
        for(int i = 1;i < n + 1;i++){
            for(int j = 1;j < m + 1;j++){
                if(s.charAt(i - 1) == t.charAt(j - 1)){
                    dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
                }else{
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return dp[n][m];
    }
}

35、两个字符串的删除操作

力扣题目链接

image-20221224160141504

思路一:

求出两个字符串的最长公共子序列长度即可,那么除了最长公共子序列之外的字符都是必须删除的,最后用两个字符串的总长度减去两个最长公共子序列的长度就是删除的最少步数。

思路二:

动规五部曲

  • 确定dp数组以及下标的含义

dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。

  • 确定递推公式

    • 当word1[i - 1] 与 word2[j - 1]相同的时候

    • 当word1[i - 1] 与 word2[j - 1]不相同的时候

​ 当word1[i - 1] 与 word2[j - 1]相同的时候,dp[i][j] = dp[i - 1][j - 1];

​ 当word1[i - 1] 与 word2[j - 1]不相同的时候,有三种情况:

​ 情况一:删word1[i - 1],最少操作次数为dp[i - 1][j] + 1

​ 情况二:删word2[j - 1],最少操作次数为dp[i][j - 1] + 1

​ 情况三:同时删word1[i - 1]和word2[j - 1],操作的最少次数为dp[i - 1][j - 1] + 2

​ 那最后当然是取最小值,所以当word1[i - 1] 与 word2[j - 1]不相同的时候,递推公式:dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1});

  • dp数组初始化

dp[i][0] 和 dp[0][j]是一定要初始化的

 for(int i = 0;i < n + 1;i++) dp[i][0] = i;
 for(int j = 0;j < m + 1;j++) dp[0][j] = j;
  • 确定遍历顺序

从递推公式 dp[i][j] = min(dp[i - 1][j - 1] + 2, min(dp[i - 1][j], dp[i][j - 1]) + 1); 和dp[i][j] = dp[i - 1][j - 1]可以看出dp[i][j]都是根据左上方、正上方、正左方推出来的。

  • 举例并推导dp数组

image-20221224155321226

Code

解法一

// dp数组中存储word1和word2最长相同子序列的长度
class Solution {
    public int minDistance(String word1, String word2) {
        int n = word1.length();
        int m = word2.length();
        int[][] dp = new int[n+1][m+1];
        for(int i = 1;i < n + 1;i++){
            for(int j = 1;j < m + 1;j++){
                if(word1.charAt(i - 1) == word2.charAt(j - 1)){
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }else{
                    dp[i][j] = Math.max(dp[i - 1][j],dp[i][j - 1]);
                }
            }
        }
        return n + m - 2*dp[n][m];
    }
}

解法二

class Solution {
    public int minDistance(String word1, String word2) {
        int n = word1.length();
        int m = word2.length();
        int[][] dp = new int[n+1][m+1];
        for(int i = 0;i < n + 1;i++) dp[i][0] = i;
        for(int j = 0;j < m + 1;j++) dp[0][j] = j;
        for(int i = 1; i < n + 1;i++){
            for(int j = 1;j < m + 1;j++){
                if(word1.charAt(i - 1) == word2.charAt(j - 1)){
                    dp[i][j] = dp[i-1][j-1];
                }else{
                    dp[i][j] = Math.min(Math.min(dp[i-1][j] + 1,dp[i][j-1]+1),dp[i-1][j-1]+2);
                }
            }
        }
        return dp[n][m];
    }
}

36、编辑距离

力扣题目链接

动规五部曲

  • 确定dp数组以及下标的含义

dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。

  • 确定递推公式
if (word1[i - 1] == word2[j - 1])
    不操作
if (word1[i - 1] != word2[j - 1])
    增
    删
    换
  • word1[i - 1] == word2[j - 1]

    • 不操作 dp[i][j] = dp[i-1][j-1]
  • word1[i - 1] != word2[j - 1]

    • 增和删等同,操作数一样
      • dp[i][j] = dp[i][j-1] + 1
      • dp[i][j] = dp[i-1][j] + 1
      • dp[i][j] = dp[i-1][j-1] + 1
    • 在增删换最小值
     dp[i][j] = Math.min(Math.min(dp[i - 1][j],dp[i][j - 1]),dp[i - 1][j - 1])+1;
    
  • dp数组初始化

p[i][0] = i;

dp[0][j] = j;

    for(int i = 0;i < n + 1;i++) dp[i][0] = i;
    for(int j = 0;j < m + 1;j++) dp[0][j] = j;
  • 确定遍历顺序

从如下四个递推公式:

  • dp[i][j] = dp[i - 1][j - 1]
  • dp[i][j] = dp[i - 1][j - 1] + 1
  • dp[i][j] = dp[i][j - 1] + 1
  • dp[i][j] = dp[i - 1][j] + 1

dp矩阵中一定是从左到右从上到下去遍历

image-20221224162301543

  • 打印并推导dp数组

以示例1为例,输入:word1 = "horse", word2 = "ros"为例,dp矩阵状态图如下:

image-20221224162400183

Code

class Solution {
    public int minDistance(String word1, String word2) {
        int n = word1.length();
        int m = word2.length();
        int[][] dp = new int[n+1][m+1];
        for(int i = 0;i < n + 1;i++) dp[i][0] = i;
        for(int j = 0;j < m + 1;j++) dp[0][j] = j;
        for(int i = 1; i < n + 1;i++){
            for(int j = 1;j < m + 1;j++){
                if(word1.charAt(i - 1) == word2.charAt(j - 1)){
                    dp[i][j] = dp[i - 1][j - 1];
                }else{
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j],dp[i][j - 1]),dp[i - 1][j - 1])+1;
                }
            }
        }
        return dp[n][m];
    }
}

37、回文子串

力扣题目链接

动规五部曲

  • 确定dp数组以及其下标的含义

布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。

  • 确定递推公式

整体上是两种,就是s[i]与s[j]相等,s[i]与s[j]不相等这两种。

当s[i]与s[j]不相等,那没啥好说的了,dp[i][j]一定是false。

当s[i]与s[j]相等时,这就复杂一些了,有如下三种情况

  • 情况一:下标i 与 j相同,同一个字符例如a,当然是回文子串
  • 情况二:下标i 与 j相差为1,例如aa,也是回文子串
  • 情况三:下标:i 与 j相差大于1的时候,例如cabac,此时s[i]与s[j]已经相同了,我们看i到j区间是不是回文子串就看aba是不是回文就可以了,那么aba的区间就是 i+1 与 j-1区间,这个区间是不是回文就看dp[i + 1][j - 1]是否为true。
                if(s.charAt(i) == s.charAt(j)){
                    if(j - i <= 1){
                        dp[i][j] = true;
                        res++;
                    }else if(dp[i+1][j-1]){
                        dp[i][j] = true;
                        res++;
  • dp数组初始化

dp[i][j]初始化为false。

  • 确定遍历顺序

dp[i + 1][j - 1] 在 dp[i][j]的左下角,如图:

image-20221224172736036

一定要从下到上,从左到右遍历,这样保证dp[i + 1][j - 1]都是经过计算的

  • 举例并推导dp数组

举例,输入:“aaa”,dp[i][j]状态如下:

image-20221224172832268

Code

class Solution {
    public int countSubstrings(String s) {
        int res = 0;
        if(s == null || s.length() == 0) return 0;
        int n = s.length();
        boolean[][] dp = new boolean[n][n];
        for(int i = n - 1;i >= 0;i--){
            for(int j = i;j < n;j++){
                if(s.charAt(i) == s.charAt(j)){
                    if(j - i <= 1){
                        dp[i][j] = true;
                        res++;
                    }else if(dp[i+1][j-1]){
                        dp[i][j] = true;
                        res++;
                    }
                }
            }
        }
         return res;
    }
}

38、最长回文子序列

力扣题目链接

动规五部曲

状态计算:判断s[i] 与 s[j]是否相等

  • s[i] == s[j]

    • dp[i][j] = dp[i + 1][j - 1] + 2
  • s[i] != s[j]:dp[i][j] = max(dp[i][j - 1], dp[i + 1][j])

    • 删除s[i]dp[i + 1][j]

    • 删除s[j]dp[i][j - 1]

  • 确定dp数组以及其下标的含义

dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度为dp[i][j]

  • 确定递推公式

如果s[i]与s[j]相同,那么dp[i][j] = dp[i + 1][j - 1] + 2;

如图:

image-20221224175802025

s[i] != s[j]:dp[i][j] = max(dp[i][j - 1], dp[i + 1][j])

如图:

image-20221224175848112

  • dp数组初始化

当i与j相同,那么dp[i][j]一定是等于1,其它情况初始化为0

  • 确定遍历顺序

遍历i的时候一定要从下到上遍历,这样才能保证,下一行的数据是经过计算的。

如图:

image-20221224180003137

  • 举例并推导dp数组

输入s:“caad” 为例,dp数组状态如图:

image-20221224180029924

Code

class Solution {
    public int longestPalindromeSubseq(String s) {
        int n = s.length();
        int[][] dp = new int[n][n];
        for(int i = n - 1; i >= 0; i--){
            dp[i][i] = 1;
            for(int j = i + 1; j < n; j++){
                if(s.charAt(i) == s.charAt(j)){
                    dp[i][j] = dp[i+1][j-1] + 2;
                }else{
                    dp[i][j] = Math.max(dp[i+1][j],dp[i][j-1]);
                }
            }
        }
        return dp[0][n-1];
    }
}

动态规划总结篇

动规五部曲

  • 确定dp数组(dp table)以及下标的含义

  • 确定递推公式

  • dp数组如何初始化

  • 确定遍历顺序

  • 举例推导dp数组

背包问题系列

image-20221224180222405

股票系列

image-20221224180333899

子序列系列

image-20221224180407568

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

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

相关文章

java论坛贴子网站ssm论坛项目发帖子网站论坛系统论坛源码

ssm开发的论坛系统&#xff0c;用户注册后可以发布帖子&#xff0c;其他人可以评论回复点赞评论和点赞回复&#xff0c;用户可以在个人中心管理自己的帖子&#xff0c;以及查看自己对他人的回复&#xff0c;和他人对自己的回复。 演示视频&#xff1a; https://www.bilibili.c…

图(Graph)的定义

图(Graph)的定义 文章目录图(Graph)的定义●图的形式化定义:G (V,E)●无向图和有向图的表示形式:● 有向图和无向图的定义●抽象数据类型定义ADT●图形结构属于复杂的非线性结构● 图由顶点的集合和边的集合构成 ●图的形式化定义:G (V,E) • 集合V(vertex):顶点的有限集合,…

多线程基础入门

文章目录前言一、认识线程&#xff08;一&#xff09;概念1.线程是什么2.为啥要有线程&#xff08;轻量级进程&#xff09;为什么线程比进程更轻量经典面试题&#xff1a;谈谈进程和线程的区别和联系3.线程的结构&#xff08;二&#xff09;第一个多线程程序&#xff08;三&…

Java中的自旋锁,手动实现一个自旋锁

自旋锁 CAS是实现自旋锁的基础&#xff0c;CAS利用CPU指令保证了操作的原子性&#xff0c;已达到锁的效果。自旋是指尝试获取锁的线程不会立即阻塞&#xff0c;而是采用循环的方式去尝试获取锁&#xff0c; 当线程发现锁被占用时&#xff0c;会不断循环判断锁的状态&#xff0…

计算机网络最新复习【太原理工大学】

课后题 Word 版&#xff0c;提取码&#xff1a;5201https://pan.baidu.com/s/13xzx8qr8Mnh4TWTS_dEYxA 目录 一、题型 二、考点 一、题型 1. 选择题 40 个&#xff0c;每个 1 分&#xff0c;共 40 分。&#xff08;大部分可一眼看出答案&#xff09; 2. 填空题 15 个&…

最长上升子序列优化(贪心+二分)(超级详细的讲解)

最长上升子序列优化&#xff08;贪心二分一、回顾1、问题描述2、动规代码弊端二、优化1、算法优化2、代码实现一、回顾 1、问题描述 2、动规代码弊端 我们之前的动规代码的时间复杂度是O(n2)O(n^2)O(n2)。如果大家还不知道动态规划的逻辑的话&#xff0c;建议大家先去看一下动…

我国用电信息采集系统行业应用需求及市场容量分析 现6省上线运行

用户用电信息采集系统是通过对配电变压器和终端用户的用电数据的采集和分析&#xff0c;实现用电监控、推行阶梯定价、负荷管理、线损分析&#xff0c;最终达到自动抄表、错峰用电、用电检查&#xff08;防窃电&#xff09;、负荷预测和节约用电成本等目的。建立全面的用户用电…

VuePress初学之利用模板theme创建一个个人博客网站

目录前言官方文档创建项目创建目录安装VuePress初始化项目创建文档修改package.json运行项目修改README.md的编码显示官方默认主题创建.vuepress文件创建config.js修改README.md补充logo资源运行效果更多默认主题配置开源主题vuepress-theme-reco安装脚手架初始化项目安装npm运…

为什么说L2毫秒接口的应用比较广泛?

和其它的数据接口一样&#xff0c;这L2毫秒接口也起到了一个媒介的作用&#xff0c;将所有的股票信息都传递到了另外一个软件上。因为市场上的股票种类很多&#xff0c;所以每一种股票都具有其特有的信息&#xff0c;是进行股票买卖的基础。 为什么说L2毫秒接口的应用比较广泛…

MCU-51:矩阵键盘

题目一、矩阵键盘介绍1.1 矩阵键盘1.2 扫描的概念二、编程2.1 LCD屏显示“HelloWord”2.2 矩阵键盘程序三、矩阵键盘应用一、矩阵键盘介绍 1.1 矩阵键盘 在键盘中按键数量较多时&#xff0c;为了减少I/O口的占用&#xff0c;通常将按键排列成矩阵形式 采用逐行或逐列的“扫描…

Flowable学习笔记(一):SpringBoot项目整合Flowable

1.基于k8s部署Mysql 参考&#xff1a;k8s部署mysql 我安装是去掉了卷挂载。安装过程可能出现磁盘容量不够&#xff0c;可以通过df -h查看。 镜像下载得比较慢&#xff0c;可以先用docker拉取镜像。 2.搭建SpringBoot项目 (1)搭建maven项目&#xff0c;pom.xml依赖如下&am…

一文带你深入理解【Java基础】· 网络编程(下)

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

我国农村水利水电行业项目投资、水电站建设及装机容量情况分析

一、农村水利水电行业投资情况 根据水利部数据显示&#xff0c;2020年农村水利水电累计下达投资428.63亿元&#xff08;其中中央投资214.84亿元&#xff0c;地方投资213.79亿元&#xff09;。其中&#xff0c;中央预算内投资97.75亿元&#xff0c;中央财政水利发展资金100.96亿…

【MindStudio训练营第一季】基于U-Net网络的图像分割的MindStudio实践

前情说明 本作业基于Windows版MindStudio 5.0.RC3&#xff0c;远程连接ECS服务器使用&#xff0c;ECS是基于官方分享的CANN6.0.RC1_MindX_Vision3.0.RC3镜像创建的。 基于ECS&#xff08;Ascend310&#xff09;的U-Net网络的图像分割 1. U-Net网络介绍&#xff1a; U-Net模…

第12章_数据库其它调优策略

第12章_数据库其它调优策略 1.数据库调优的措施 1.1调优的目标 尽可能节省系统资源&#xff0c;以便系统可以提供更大负荷的服务。(吞吐量更大)。合理的结构设计和参数调整&#xff0c;以提高用户操作响应的速度。(响应速度更快)减少系统的瓶颈&#xff0c;提高MySQL数据库整…

PCL 基于最小生成树(MST)获取单木骨架(粗)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 提取的过程大体上分为两个部分:生成单木MST(最小生成树)以及基于该MST获取大致的骨架结构(线条)。 具体的计算过程如下所述: 1、首先应用Delaunay三角剖分来构造初始图。Delaunay三角剖分是MST计算的基础,因…

【SQL优化】union 与 union all 的区别

先说结论&#xff1a; union all:合并查询结果 union:合并查询结果 && 去重 && 排序 &#xff08;所以 union 比union all 功能多&#xff0c;性能就会稍微差一点&#xff09; 推导过程&#xff1a; 假设有这样一张表&#xff0c;里面有4条数据 union操作…

win环境mysql版本升级到5.7过程

win环境mysql版本升级到5.7过程&#xff0c;我win电脑里mysql版本是5.0&#xff0c;版本太老了&#xff0c;也不支持和nacos集成&#xff08;nacos至少需要5.6版本的mysql&#xff09;&#xff0c;思来想去还是要升级一下自己电脑的mysql版本&#xff0c;保守点升级到5.7吧&…

Apache Hive DML语句与函数使用

Hive SQL 加载数据 之前我们加载数据是&#xff0c;创建一张表&#xff0c;将结构化文件放到hadoop对应表路径下。这样我们就将表和文件进行映射了。但是这样比较暴力&#xff0c;官方不推荐。 这样的操作是直接跳过了Hive Load加载数据 语法&#xff1a; load data [local]…

【编译原理】实验一:熟悉实验环境VSCode并完成正则表达式转换为NFA

目录 实验一 熟悉实验环境VSCode并完成正则表达式转换为NFA 一、实验目的 二、预备知识 三、实验内容 VSCode的基本使用方法 安装和启动VSCode VSCode的窗口布局 使用VSCode将项目克隆到本地磁盘 使用VSCode登录平台 查看项目中的文件 实验源代码 演示程序的执行过程 四、实验过…