【算法】数位DP

news2024/11/24 10:44:44

文章目录

  • 数位DP
    • 前置知识——位运算与集合论
  • 例题——2376. 统计特殊整数
    • 思路
    • 代码模板(重要!⭐⭐⭐⭐⭐)
      • 针对这道题,可以去掉 isNum 参数
  • 相关题目练习
    • 233. 数字 1 的个数⭐⭐⭐⭐⭐
      • 代码模板修改——记录cnt(前面已经选了几个1)
        • 代码优化——不需要isNum
    • 面试题 17.06. 2出现的次数
    • 600. 不含连续1的非负整数⭐⭐⭐
    • 902. 最大为 N 的数字组合
    • 1067. 范围内的数字计数
    • 1397. 找到所有好字符串⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
      • 数位dp + kmp
        • 代码1——kmp风格1
        • 代码2——kmp风格2(j从-1开始)👍👍👍👍👍
        • kmp应用的相关题目——1392. 最长快乐前缀
          • 解法1——kmp
          • 解法2——Rabin-Karp 字符串编码
    • 1012. 至少有 1 位重复的数字
      • 解法——转换(统计特殊整数)
    • 2719. 统计整数数目⭐⭐⭐

数位DP

https://www.bilibili.com/video/BV1rS4y1s721/
可以看完视频讲解之后直接写例题,学模板。

当前位填的数字会受到前面填的数字的约束

前置知识——位运算与集合论

在这里插入图片描述

两个关键的式子:
x >> d & 1
x | (1 << d)

>> 和 & 的运算优先级是一样的,所以从左往右进行计算。

例题——2376. 统计特殊整数

https://leetcode.cn/problems/count-special-integers/
在这里插入图片描述

思路

https://leetcode.cn/problems/count-special-integers/solutions/1746956/shu-wei-dp-mo-ban-by-endlesscheng-xtgx/
在这里插入图片描述

代码模板(重要!⭐⭐⭐⭐⭐)

用 mask 记录已经选了哪些数字
用 isNum 记录是否前面都是前导零

class Solution {
    char[] s;
    int[][] memo;

    public int countSpecialNumbers(int n) {
        s = String.valueOf(n).toCharArray();
        int m = s.length;
        memo = new int[m][1 << 10];
        for (int i = 0; i < m; ++i) {
            Arrays.fill(memo[i], -1);   // -1表示没有被计算过
        }
        // 从下标0开始填,初始mask=0,isLimit=true,isNum=false
        return f(0, 0, true, false);
    }

    // 返回从i开始填数字,i前面填的数字的集合是mask,能构造出的特殊正数的数目
    // isLimit表示前面填的数字是否都是n对应位上的,如果为true,那么当前位至多为s[i],否则至多为'9'
    // isNum表示前面是否填了数字(是否跳过),如果为true,那么当前位可以从0开始,如果为false,那么我们可以跳过或者从1开始填数字   这个是为了处理无效的前导零(isNum=true表示前面都是前导零被跳过了)
    int f(int i, int mask, boolean isLimit, boolean isNum) {
        if (i == s.length) return isNum? 1: 0;
        if (!isLimit && isNum && memo[i][mask] != -1) return memo[i][mask];
        int res = 0;
        // 可以跳过当前位
        if (!isNum) res = f(i + 1, mask, false, false);
        // 如果前面填的数字都和n一样,那么这一位至多填数字s[i](否则就超过n了)
        int up = isLimit? s[i] - '0': 9;
        for (int d = isNum? 0: 1; d <= up; ++d) {
            if ((mask >> d & 1) == 0) {
                res += f(i + 1, mask | (1 << d), isLimit && d == up, true);
            }
        }
        if (!isLimit && isNum) memo[i][mask] = res;
        return res;
    }
}

一定要注意!
memo[i][mask] 记录的是当 !isLimit && isNum 时 对应 i 和 mask 的结果。(即不受约束且是数字

因为真正 isLimit = true 到最后只有一次计算;(因为 true 就表示前面选择的数字的各位和 n 的各位是一样的。)
同理 isNum = false 时也是。(因为 false 就表示前面选择的数字都是前导零。)
这些情况在递归的过程中都只会遇到一次。

在这里插入图片描述
这里的状态个数为 l e n ( s ) ∗ 2 1 0 len(s) * 2^10 len(s)210,即 m ∗ 2 D m * 2^D m2D ,这里的 D = 10, 2 D 2 ^ D 2D即为 mask 的数量。

针对这道题,可以去掉 isNum 参数

由于 mask 中记录了数字,可以通过判断 mask 是否为 0 来判断前面是否填了数字,所以 isNum 可以省略

代码如下:

class Solution {
    char[] s;
    int[][] memo;

    public int countSpecialNumbers(int n) {
        s = String.valueOf(n).toCharArray();
        int m = s.length;
        memo = new int[m][1 << 10];
        for (int i = 0; i < m; ++i) {
            Arrays.fill(memo[i], -1);   // -1表示没有被计算过
        }
        // 从下标0开始填,初始mask=0,isLimit=true
        return f(0, 0, true);
    }

    // 返回从i开始填数字,i前面填的数字的集合是mask,能构造出的特殊正数的数目
    // isLimit表示前面填的数字是否都是n对应位上的,如果为true,那么当前位至多为s[i],否则至多为'9'
    int f(int i, int mask, boolean isLimit) {
        if (i == s.length) return mask != 0? 1: 0;
        if (!isLimit && mask != 0 && memo[i][mask] != -1) return memo[i][mask];
        int res = 0;
        // 可以跳过当前位
        if (mask == 0) res = f(i + 1, mask, false);
        // 如果前面填的数字都和n一样,那么这一位至多填数字s[i](否则就超过n了)
        int up = isLimit? s[i] - '0': 9;
        for (int d = mask != 0? 0: 1; d <= up; ++d) {
            if ((mask >> d & 1) == 0) {
                res += f(i + 1, mask | (1 << d), isLimit && d == up);
            }
        }
        if (!isLimit && mask != 0) memo[i][mask] = res;
        return res;
    }
}

相关题目练习

233. 数字 1 的个数⭐⭐⭐⭐⭐

https://leetcode.cn/problems/number-of-digit-one/
在这里插入图片描述

代码模板修改——记录cnt(前面已经选了几个1)

memo[i][j] 表示枚举到第 i 个下标时前面已经选择了 j 个1。

即 memo 数组的第二个维度是 cnt

class Solution {
    char[] s;
    int[][] memo;

    public int countDigitOne(int n) {
        s = Integer.toString(n).toCharArray();
        int m = s.length;
        memo = new int[m][m];
        for (int i = 0; i < m; ++i) Arrays.fill(memo[i], -1);
        return f(0, true, false, 0);  // 最后一个参数表示前面选了几个1;    
    }

    public int f(int i, boolean isLimit, boolean isNum, int cnt) {
        if (i == s.length) return cnt;
        if (!isLimit && isNum && memo[i][cnt] != -1) return memo[i][cnt];
        
        int res = 0;
        if (!isNum) res = f(i + 1, false, false, 0);
        int up = isLimit? s[i] - '0': 9;
        for (int d = isNum? 0: 1; d <= up; ++d) {
            res += f(i + 1, isLimit && d == up, true, cnt + (d == 1? 1: 0));
        }
        if (!isLimit && isNum) memo[i][cnt] = res;
        return res;
    }
}

代码优化——不需要isNum

这道题目不需要 isNum,因为就算是前导零,也不会影响 数字中 1 的个数。

class Solution {
    char[] s;
    int[][] memo;

    public int countDigitOne(int n) {
        s = Integer.toString(n).toCharArray();
        int m = s.length;
        memo = new int[m][m];
        for (int i = 0; i < m; ++i) Arrays.fill(memo[i], -1);
        return f(0, true, 0);  // 最后一个参数表示前面选了几个1;    
    }

    public int f(int i, boolean isLimit, int cnt) {
        if (i == s.length) return cnt;
        if (!isLimit && memo[i][cnt] != -1) return memo[i][cnt];
        
        int res = 0;
        int up = isLimit? s[i] - '0': 9;
        for (int d = 0; d <= up; ++d) {
            res += f(i + 1, isLimit && d == up, cnt + (d == 1? 1: 0));
        }
        if (!isLimit) memo[i][cnt] = res;
        return res;
    }
}

面试题 17.06. 2出现的次数

https://leetcode.cn/problems/number-of-2s-in-range-lcci/
在这里插入图片描述
这道题目和上面那道题目几乎一模一样。

AC 代码如下:

class Solution {
    int[][] memo;
    char[] s;

    public int numberOf2sInRange(int n) {
        s = Integer.toString(n).toCharArray();
        int m = s.length;
        memo = new int[m][m];
        return f(0, true, 0);
    }

    public int f(int i, boolean isLimit, int cnt) {
        if (i == s.length) return cnt;
        if (!isLimit && memo[i][cnt] !=0) return memo[i][cnt];

        int res = 0, up = isLimit? s[i] - '0': 9;
        for (int d = 0; d <= up; ++d) {
            res += f(i + 1, isLimit && d == up, cnt + (d == 2? 1: 0));
        }
        if (!isLimit) memo[i][cnt] = res;
        return res;
    }
}

600. 不含连续1的非负整数⭐⭐⭐

600. 不含连续1的非负整数
在这里插入图片描述

将问题转换成只能选择 0 和 1 ,且 1 之间不能连续出现的数位 dp 问题即可。

class Solution {
    char[] s;
    int[][] memo;

    public int findIntegers(int n) {
        s = Integer.toBinaryString(n).toCharArray();
        int m = s.length;
        memo = new int[m][2];
        for (int i = 0; i < m; ++i) Arrays.fill(memo[i], -1);
        return f(0, true, 0);
    }

    public int f(int i, boolean isLimit, int last) {
        if (i == s.length) return 1;
        if (!isLimit && memo[i][last] != -1) return memo[i][last];

        int up = isLimit? s[i] - '0': 1;

        int res = f(i + 1, isLimit && up == 0, 0);
        if (last != 1 && up == 1) res += f(i + 1, isLimit && up == 1, 1) ;
        if (!isLimit) memo[i][last] = res;
        return res;
    }
}

902. 最大为 N 的数字组合

902. 最大为 N 的数字组合

在这里插入图片描述

class Solution {
    Set<Integer> digits = new HashSet();
    char[] s;
    int[] memo;

    public int atMostNGivenDigitSet(String[] digits, int n) {
        for (String d: digits) this.digits.add(Integer.parseInt(d));
        s = String.valueOf(n).toCharArray();
        int m = s.length;
        memo = new int[m];
        Arrays.fill(memo, -1);   // -1表示没有被计算过
        // 从下标0开始填,isLimit=true,isNum=false
        return f(0, true, false);
    }

    public int f(int i, boolean isLimit, boolean isNum) {
        if (i == s.length) return isNum? 1: 0;
        if (!isLimit && isNum && memo[i] != -1) return memo[i];
        int res = 0;
        // 可以跳过当前位
        if (!isNum) res = f(i + 1, false, false);
        // 如果前面填的数字都和n一样,那么这一位至多填数字s[i](否则就超过n了)
        int up = isLimit? s[i] - '0': 9;
        for (int d = isNum? 0: 1; d <= up; ++d) {
            if (digits.contains(d)) {
                res += f(i + 1, isLimit && d == up, true);
            }
        }
        if (!isLimit && isNum) memo[i] = res;
        return res;
    }
}

删去了 mask ,因为它允许数字重复。
增加了一个可选数字集合 digits,每一位可选的数字必须在这个集合内。

在这里插入图片描述

1067. 范围内的数字计数

https://leetcode.cn/problems/digit-count-in-range/
在这里插入图片描述

上面题目的变式题。

class Solution {
    char[] s;
    int[][] memo;
    int t;

    public int digitsCount(int d, int low, int high) {
        t = d;
        return op(high) - op(low - 1);
    }

    public int op(int n) {
        s = Integer.toString(n).toCharArray();
        int m = s.length;
        memo = new int[m][m];
        for (int i = 0; i < m; ++i) Arrays.fill(memo[i], -1);
        return f(0, true, false, 0);
    }

    public int f(int i, boolean isLimit, boolean isNum, int cnt) {
        if (i == s.length) return cnt;
        if (!isLimit && isNum && memo[i][cnt] != -1) return memo[i][cnt];
        
        int res = 0;
        if (!isNum) res = f(i + 1, false, false, 0);	// 前面是前导零,这里可以也跳过设置成零
        int up = isLimit? s[i] - '0': 9;
        for (int d = isNum? 0: 1; d <= up; ++d) {
            res += f(i + 1, isLimit && d == up, true, cnt + (d == t? 1: 0));
        }
        if (!isLimit && isNum) memo[i][cnt] = res;
        return res;
    }
}

最开始写的时候忘记了 if (!isNum) res = f(i + 1, false, false, 0); 这一句。

1397. 找到所有好字符串⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

1397. 找到所有好字符串

在这里插入图片描述

这题超级难!

数位dp + kmp

关于 kmp 可见:我一定要 学会KMP字符串匹配 。

代码1——kmp风格1

https://leetcode.cn/problems/find-all-good-strings/solutions/2195814/ling-shen-shu-wei-dpmo-ban-kmp-by-zachar-qcoo/

class Solution {
    int n;
    int[][] dp;
    int[] next;
    int MOD = (int)1e9 + 7;

    public int findGoodStrings(int n, String s1, String s2, String evil) {
        this.n = n;
        int len = evil.length();
        dp = new int[n][len];
        for(int i = 0; i < n; i++) {
            Arrays.fill(dp[i], -1);
        }

        next = new int[len];
        for(int j = 0, i = 1; i < len; i++) {
            while(j > 0 && evil.charAt(i) != evil.charAt(j)) j = next[j - 1];
            if(evil.charAt(i) == evil.charAt(j)) j++;
            next[i] = j;
        }
        
        return dfs(s1, s2, evil, 0, 0, true, true);
    }

    public int dfs(String s1, String s2, String evil, int i, int j, boolean downLimited, boolean upLimited) {
        // 代表字符串中出现了 evil
        if(j == evil.length()) return 0;
        if(i == n) return 1;
        if(!downLimited && !upLimited && dp[i][j] != -1) return dp[i][j];

        long ans = 0;
        char down = downLimited ? s1.charAt(i) : 'a', up = upLimited ? s2.charAt(i) : 'z';
        for(char k = down; k <= up; k++) {
            int nj = j;
            while(nj > 0 && k != evil.charAt(nj)) nj = next[nj - 1];
            // 此处要注意,当 nj == 0 的时候,会存在 k != evil.charAt(nj) 的情况
            // 若直接 nj + 1 进入递归,是认为此时的两个字符一定是匹配上了,实际上可能并没有
            if(nj == 0 && k != evil.charAt(nj)) nj = -1;
            ans = (ans + dfs(s1, s2, evil, i + 1, nj + 1, downLimited && k == down, upLimited && k == up)) % MOD;
        }
        if(!downLimited && !upLimited) dp[i][j] = (int)ans;
        return (int)ans;
    }
}

代码2——kmp风格2(j从-1开始)👍👍👍👍👍

这是笔者自己根据上面代码修改来的。

dp[i][j] 表示枚举到第 i 位,前面匹配成功了evil 中的 j + 1 个字符(即 j 是 evil 的下标)。

class Solution {
    int n;
    int[][] dp;
    int[] next;     // kmp的next数组
    int MOD = (int)1e9 + 7;

    public int findGoodStrings(int n, String s1, String s2, String evil) {
        this.n = n;
        int len = evil.length();
        dp = new int[n][len];
        for(int i = 0; i < n; i++) {
            Arrays.fill(dp[i], -1);
        }

        next = new int[len];
        next[0] = -1;
        for(int j = -1, i = 1; i < len; i++) {
            while(j != -1 && evil.charAt(i) != evil.charAt(j + 1)) j = next[j];
            if(evil.charAt(i) == evil.charAt(j + 1)) j++;
            next[i] = j;
        }
        
        // 注意j初始为-1,表示一个都还没被匹配到
        return dfs(s1, s2, evil, 0, -1, true, true);
    }

    public int dfs(String s1, String s2, String evil, int i, int j, boolean downLimited, boolean upLimited) {
        // 代表字符串中出现了 evil
        if(j == evil.length() - 1) return 0;
        if(i == n) return 1;
        if(!downLimited && !upLimited && dp[i][j + 1] != -1) return dp[i][j + 1];   // 注意所有的dp都是dp[i][j + 1],因为j是从-1开始的

        long ans = 0;
        char down = downLimited ? s1.charAt(i) : 'a', up = upLimited ? s2.charAt(i) : 'z';
        for(char k = down; k <= up; k++) {
            // kmp的匹配过程
            int nj = j;
            while(nj != -1 && k != evil.charAt(nj + 1)) nj = next[nj];
            if (k == evil.charAt(nj + 1)) nj++;
            ans = (ans + dfs(s1, s2, evil, i + 1, nj, downLimited && k == down, upLimited && k == up)) % MOD;
        }
        if(!downLimited && !upLimited) dp[i][j + 1] = (int)ans;
        return (int)ans;
    }
}

kmp应用的相关题目——1392. 最长快乐前缀

1392. 最长快乐前缀

解法1——kmp

kmp 的 next 数组即为最长公共前后缀数组。

class Solution {
    public String longestPrefix(String s) {
        int n = s.length();
        int[] next = new int[n];
        next[0] = -1;
        for (int i = 1, j = -1; i < n; ++i) {
            while (j != -1 && s.charAt(i) != s.charAt(j + 1)) j = next[j];
            if (s.charAt(i) == s.charAt(j + 1)) j++;
            next[i] = j;
        }
        return s.substring(0, next[n - 1] + 1);
    }
}
解法2——Rabin-Karp 字符串编码

解析见:https://leetcode.cn/problems/longest-happy-prefix/solutions/172436/zui-chang-kuai-le-qian-zhui-by-leetcode-solution/

class Solution {
    public String longestPrefix(String s) {
        int n = s.length();
        long prefix = 0, suffix = 0;
        long base = 31, mod = 1000000007, mul = 1;
        int happy = 0;
        for (int i = 1; i < n; ++i) {
            prefix = (prefix * base + (s.charAt(i - 1) - 'a')) % mod;
            suffix = (suffix + (s.charAt(n - i) - 'a') * mul) % mod;
            if (prefix == suffix) {
                happy = i;
            }
            mul = mul * base % mod;
        }
        return s.substring(0, happy);
    }
}

1012. 至少有 1 位重复的数字

1012. 至少有 1 位重复的数字
在这里插入图片描述

解法——转换(统计特殊整数)

用 n - 2376. 统计特殊整数 的结果就好了。

代码如下:

class Solution {
    char[] s;
    int[][] memo;

    public int numDupDigitsAtMostN(int n) {
        return n - countSpecialNumbers(n);
    }

    public int countSpecialNumbers(int n) {
        s = String.valueOf(n).toCharArray();
        int m = s.length;
        memo = new int[m][1 << 10];
        for (int i = 0; i < m; ++i) {
            Arrays.fill(memo[i], -1);   // -1表示没有被计算过
        }
        // 从下标0开始填,初始mask=0,isLimit=true
        return f(0, 0, true);
    }

    // 返回从i开始填数字,i前面填的数字的集合是mask,能构造出的特殊正数的数目
    // isLimit表示前面填的数字是否都是n对应位上的,如果为true,那么当前位至多为s[i],否则至多为'9'
    int f(int i, int mask, boolean isLimit) {
        if (i == s.length) return mask != 0? 1: 0;
        if (!isLimit && mask != 0 && memo[i][mask] != -1) return memo[i][mask];
        int res = 0;
        // 可以跳过当前位
        if (mask == 0) res = f(i + 1, mask, false);
        // 如果前面填的数字都和n一样,那么这一位至多填数字s[i](否则就超过n了)
        int up = isLimit? s[i] - '0': 9;
        for (int d = mask != 0? 0: 1; d <= up; ++d) {
            if ((mask >> d & 1) == 0) {
                res += f(i + 1, mask | (1 << d), isLimit && d == up);
            }
        }
        if (!isLimit && mask != 0) memo[i][mask] = res;
        return res;
    }
}

2719. 统计整数数目⭐⭐⭐

https://leetcode.cn/problems/count-of-integers/

在这里插入图片描述
在这里插入图片描述

class Solution {
    char[] s;
    int[][] memo;
    int minSum, maxSum;
    final int mod = (int)1e9 + 7;

    public int count(String num1, String num2, int min_sum, int max_sum) {
        minSum = min_sum;
        maxSum = max_sum;
        int ans = op(num2) - op(num1) + mod;
        // 单独计算num1是否是合法的数字
        int sum = 0;
        for (char c: num1.toCharArray()) sum += c - '0';
        if (min_sum <= sum && sum <= max_sum) ans++;
        return ans % mod;
    }

    public int op(String num) {
        s = num.toCharArray();
        int m = s.length;
        memo = new int[m][Math.min(9 * m, maxSum) + 1];
        for (int i = 0; i < m; ++i) Arrays.fill(memo[i], -1);
        return f(0, true, 0);
    }

    public int f(int i, boolean isLimit, int digitSum) {
        if (digitSum > maxSum) return 0;    // 非法数字
        if (i == s.length) return digitSum >= minSum ? 1: 0;
        if (!isLimit && memo[i][digitSum] != -1) return memo[i][digitSum];

        int res = 0;
        int up = isLimit? s[i] - '0': 9;
        for (int d = 0; d <= up; ++d) {
            res = (res + f(i + 1, isLimit && d == up, digitSum + d)) % mod;
        }
        if (!isLimit) memo[i][digitSum] = res;
        return res;
    }
}

这里由于 num1 是个字符串,所以直接计算 <= num1 的合法数字个数,再单独判断 num1 这个数是否合法。

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

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

相关文章

Docker(三)之容器管理工具 Docker生态架构及部署

容器管理工具Docker生态架构及部署 一、Docker生态架构 1.1 Docker Containers Are Everywhere 1.2 生态架构 1.2.1 Docker Host 用于安装Docker daemon的主机&#xff0c;即为Docker Host&#xff0c;并且该主机中可基于容器镜像运行容器。 1.2.2 Docker daemon 用于管理…

基础篇-STM32初体验

MDK5编译例程 串口下载程序 DAP下载程序 DAP调试程序

多领域入选!棱镜七彩上榜《嘶吼2023网络安全产业图谱》

2023年7月10日&#xff0c;国内网络安全行业第三方研究机构嘶吼安全产业研究院联合国家网络安全产业园区&#xff08;通州园&#xff09;正式发布《嘶吼2023网络安全产业图谱》&#xff0c;棱镜七彩凭借在开源安全领域的创新性及服务能力&#xff0c;上榜开发与应用、应用于产业…

解决2003-Host‘ ‘is not allowed to connect to this MySQL server,实现远程连接本地数据库

目录 1.打开终端控制面板 2.进入mysql库 3.执行更新权限语句 4.查看权限 5.刷新服务器配置 6.进入Navict测试连接 在使用Navicat远程连接本地数据库时&#xff0c;遇到了这样一个问题&#xff0c; 我使用 本地主机的地址&#xff0c;连接本地的数据库&#xff0c;报错host…

(CentOS 7)nvidia-smi:Failed to initialize NVML: Driver/library version mismatch

[CentOS 7]nvidia-smi:Failed to initialize NVML: Driver/library version mismatch 问题源头&#xff1a; nvidia-smi \text{nvidia-smi} nvidia-smi报错问题 CUDA \text{CUDA} CUDA安装时的问题 这里仅描述自身发现的一种情况&#xff0c;希望对大家有所帮助。 问题源头&…

JMX+Prometheus监控Grafana展示

文章目录 概述Java代码使用PrometheusApi统计监控指标PrometheusGrafana展示 概述 最近在阅读InLong的源码&#xff0c;发现它采用通过JMXPrometheus进行指标监控。 这里做了下延伸将介绍使用JMXPrometheusGrafana进行监控指标展示&#xff0c;这里单独将Metric部分代码抽离出…

网络配置管理器中的系统日志配置

包含许多设备的大型网络基础设施将在其清单中具有某些重要和关键设备&#xff0c;例如核心路由器或防火墙。这些设备必须始终受到有关任何配置更改的持续监视。 在如此庞大的网络中&#xff0c;手动跟踪所有这些重要设备并在每次进行新更改时触发备份几乎是不可能的。如果管理…

windows环境部署seata注意事项

1.将seata放置微服务项目中&#xff1a; 1.服务端下载地址&#xff1a;https://github.com/seata/seata/releases/download/v1.4.2/seata-server-1.4.2.zip 2.源码下载地址: https://github.com/seata/seata &#xff08;将script目录以及里面文件放至seata-server中&#xff…

力扣挑战:中枢整数的定义与寻找方法

本篇博客讲解力扣“2485. 找出中枢整数”的解题思路&#xff0c;这是题目链接。 给定一个正整数n&#xff0c;如果它存在一个中枢整数x&#xff0c;那么满足以下等式&#xff1a; 123…x x(x1)(x2)…n 利用等差数列求和公式&#xff1a;(首项末项)项数2&#xff0c;以及项数…

优思学院|TQM与六西格玛完美契合:质量和利润的共赢之道

TQM的本质乃无止境地追求质量&#xff0c;然而在解决各个问题点时&#xff0c;直到目的逹成之前必须不断地转动PDCA或者六西格玛方法中的DMAIC这些个活动&#xff0c;究竟与经营有什么关连呢&#xff1f; 我们都知道企业的目的是生产好的产品、提供好的服务&#xff0c;并以合…

火热的低代码和无代码赛道

一、背景 星霜荏苒&#xff0c;居诸不息。互联网技术飞速发展&#xff0c;软件的设计、开发、应用也是风发泉涌&#xff0c;无论是开发工具还是应用程序&#xff0c;都在不断追求降本增效&#xff0c;极大地推动了软件研发的长足进步。但然而&#xff0c;长期以来&#xff0c;我…

elementui-drawer模板

1、效果图 2、上代码 <template><div><el-drawersize"100%":visible.sync"drawer"style"position: absolute;"class"details":modal-append-to-body"false":modal "false":before-close"ha…

Linux环境基础开发工具使用(yum软件安装工具的使用、vim编辑器使用及握gcc/g++编译器的使用等)

Linux环境基础开发工具使用 1.Linux 软件包管理器 yum1.1 什么是软件包1.2 yum常用命令1.3 好玩的yum包 2.Linux开发工具2.1 vim工具的由来2.2 vim模式①基本模式②派生模式 2.3 vim的基本操作2.4 vim正常模式命令集2.5 vim末行模式命令集2.6 简单vim配置 3.Linux编译器 - gcc/…

并发容器(三)BlockigQueue

阻塞队列 看几个常用的实现&#xff1a; 1.ArrayBlockingQueue是最简单的一种阻塞队列&#xff0c;底层是由数组实现 2.LinkedBlockingQueue 底层是由链表实现的&#xff0c;锁的粒度更细&#xff0c;但是占用的内存更大 当移除元素的时候takeLock和putLock一起加 3.Synchrono…

HCIP第七天

题目 拓扑图 1.所有路由器各自创建一个环回接口&#xff0c;合理规划IP地址 测试 2. R1-R2-R3-R4-R6之间使用OSPF协议&#xff0c;R4-R5-R6之间使用RIP协议 3. R1环回重发布方式引入OSPF网络 4. R4/R6上进行双点双向重发布 将OSPF中的环回接口改成broadcast 因为华为默认环回接…

用ChatGPT解析Wireshark抓取的数据包样例

用Wireshark抓取的数据包&#xff0c;常用于网络故障排查、分析和应用程序通信协议开发。其抓取的分组数据结果为底层数据&#xff0c;看起来比较困难&#xff0c;现在通过chatGPT大模型&#xff0c;可以将原始抓包信息数据提交给AI进行解析&#xff0c;本文即是进行尝试的样例…

4.4Java EE——多对多查询

订单和商品多对多关系图 在实际项目开发中&#xff0c;多对多的关联关系非常常见。以订单和商品为例&#xff0c;一个订单可以包含多种商品&#xff0c;而一种商品又可以属于多个订单&#xff0c;订单和商品属于多对多关联关系&#xff0c;订单和商品之间的关联关系如图。 在数…

springboot家政服务管理平台

本系统为了数据库结构的灵活性所以打算采用MySQL来设计数据库&#xff0c;而java技术&#xff0c;B/S架构则保证了较高的平台适应性。本文主要介绍了本系统的开发背景&#xff0c;所要完成的功能和开发的过程&#xff0c;主要说明了系统设计的重点、设计思想。 本系统主要是设…

通信算法之177: 基于Matlab的OFDM通信系统关键基带算法设计7-流程

一. 接收算法流程 1.1 粗同步&#xff08;分组检测&#xff09; 1.2 载波同步&#xff08;精细频偏估计&#xff09; 多普勒频偏和晶振。频率偏差&#xff0c;会破坏子载波间的正交性&#xff0c;且这种频差对相位的影响还具有累加性。 1.3 精同步&#xff08;OFDM起始&…

软件工程——第10章面向对象分析知识点整理

本专栏是博主个人笔记&#xff0c;主要目的是利用碎片化的时间来记忆软工知识点&#xff0c;特此声明&#xff01; 文章目录 1.分析工作主要包括哪三项内容&#xff1f; 2.面向对象分析是一个怎样的过程&#xff1f; 3.需求陈述是一成不变的吗&#xff1f; 4.复杂问题的对象…