【动态规划】 深入动态规划 回文子串问题

文章目录

  • 前言
  • 例题
    • 一、回文子串
    • 二、 最长回文子串
    • 三、回文串分割IV
    • 四、分割回文串II
    • 五、最长回文子序列
    • 六、让字符串成为回文串的最小插入次数
  • 结语


在这里插入图片描述

前言

那么,什么是动态规划中的回文子串问题呢?

动态规划中的回文子串问题是一个经典的字符串处理问题。具体描述为:给定一个字符串,要求找出该字符串中所有的回文子串。回文子串是指从左到右和从右到左读起来都一样的字符串片段。
例如,对于字符串 “abcba”,其中的 “a”“b”“c”“aba”“bcb”“abcba” 都是回文子串。
解决这个问题通常使用动态规划的方法。定义一个二维布尔数组dp[i][j],表示字符串中从索引i到索引j的子串是否为回文子串。初始化时,单个字符一定是回文子串,即dp[i][i] = true。然后,从长度为 2 的子串开始逐步计算到整个字符串的长度。对于长度大于 1 的子串,如果两端字符相等,即s[i] == s[j],并且去掉两端字符后的子串也是回文子串,即dp[i + 1][j - 1] = true,那么这个子串就是回文子串,dp[i][j] = true。通过这样的动态规划过程,可以高效地找出字符串中的所有回文子串,时间复杂度通常为O(n2),其中n是字符串的长度。

下面本文将通过以例题的形式详细阐述动态规划中的回文子串问题。

例题

一、回文子串

  1. 题目链接:回文子串
  2. 题目描述:

给你⼀个字符串 s ,请你统计并返回这个字符串中 回文字串的数目。 回文字符串 是正着读和倒过来读⼀样的字符串。 ⼦字符串 是字符串中的由连续字符组成的⼀个序列。 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
示例 1:
输入:s = “abc”
输出:3
解释:三个回文子串: “a”, “b”, “c”
示例 2:
输入:s = “aaa”
输出:6
解释:6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”
提示:1 <= s.length <= 1000
s 由小写英文字母组成

  1. 解法(动态规划): 算法思路: 我们可以先「预处理」⼀下,将所有子串「是否回文」的信息统计在 dp 表里面,然后直接在表里面统计 true 的个数即可。
    状态表示:为了能表示出来所有的子串,我们可以创建⼀个 n * n 的⼆维 dp 表,只用到「上三角部分」 即可。 其中, dp[i][j] 表示: s 字符串 [i, j] 的子串,是否是回文串。
    状态转移方程: 对于回文串,我们一般分析一个「区间两头」的元素:
    i. 当 s[i] != s[j] 的时候:不可能是回⽂串, dp[i][j] = 0 ;
    ii. 当 s[i] == s[j] 的时候:根据⻓度分三种情况讨论:
    • 长度为 1 ,也就是 i == j :此时⼀定是回文串, dp[i][j] = true ;
    • 长度为 2 ,也就是 i + 1 == j :此时也⼀定是回文串, dp[i][j] = true ;
    • 长度大于 2 ,此时要去看看 [i + 1, j - 1] 区间的子串是否回文: dp[i][j] = dp[i + 1][j - 1] 。 综上,状态转移方程分情况谈论即可。
    初始化:因为我们的状态转移方程分析的很细致,因此无需初始化。
    填表顺序: 根据「状态转移方程」,我们需要「从下往上」填写每⼀行,每⼀行的顺序无所谓。
    返回值: 根据「状态表示和题母要求」,我们需要返回 dp 表中 true 的个数。

  2. 代码示例:

 public int countSubstrings(String s) {// 1. 创建 dp 表// 2. 初始化// 3. 填表// 4. 返回值int n = s.length();boolean[][] dp = new boolean[n][n];int ret = 0;for (int i = n - 1; i >= 0; i--) {for (int j = i; j < n; j++) {if (s.charAt(i) == s.charAt(j))dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;if (dp[i][j])ret++;}}return ret;}

二、 最长回文子串

  1. 题目链接:最长回文子串
  2. 题目描述:

给你⼀个字符串 s,找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1: 输入:s = “babad” 输出:“bab” 解释:“aba” 同样是符合题意的答案。
示例 2: 输入:s = “cbbd” 输出:“bb”
提示:1 <= s.length <= 1000
s 仅由数字和英文字母组成

  1. 解法(动态规划):
    算法思路:
    a. 我们可以先⽤ dp 表统计出「所有子串是否回文」的信息
    b. 然后根据 dp 表示 true 的位置,得到回文串的「起始位置」和「长度」。
    那么我们就可以在表中找出最长回文串

  2. 代码示例:

public String longestPalindrome(String s) {// 1. 创建 dp 表// 2. 初始化// 3. 填表// 4. 返回值int n = s.length();boolean[][] dp = new boolean[n][n];int begin = 0, len = 1; // 标记⼀下最⻓⼦串的起始位置和⻓度for (int i = n - 1; i >= 0; i--) {for (int j = i; j < n; j++) {if (s.charAt(i) == s.charAt(j))dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;if (dp[i][j] && j - i + 1 > len) {len = j - i + 1;begin = i;}}}return s.substring(begin, begin + len);}

三、回文串分割IV

  1. 题目链接:回文串分割IV
  2. 题目描述:

给你⼀个字符串 s ,如果可以将它分割成三个非空回文子字符串,那么返回 true ,否则返 回 false 。 当⼀个字符串正着读和反着读是⼀模⼀样的,就称其为回文字符串 。
示例 1: 输入:s = “abcbdd” 输出:true
解释:“abcbdd” = “a” + “bcb” + “dd”,三个⼦字符串都是回⽂的。
示例 2: 输入:s = “bcbddxy” 输出:false
解释:s 没办法被分割成 3 个回文子字符串。
提⽰: 3 <= s.length <= 2000
s 只包含⼩写英⽂字⺟。

  1. 解法(动态规划):
    算法思路: 题目要求⼀个字符串被分成「三个非空回文子串」,乍⼀看,要表⽰的状态很多,有些无从下手。 其实,我们可以把它拆成「两个小问题」:
    i. 动态规划求解字符串中的⼀段非空子串是否是回文串;
    ii. 枚举三个子串除字符串端点外的起止点,查询这三段非空子串是否是回文串。 那么这道困难题就免秒变为简单题啦,变成了⼀道枚举题。

  2. 代码示例:

 public boolean checkPartitioning(String s) {// 1. 利⽤ dp 处理⼀下所有的⼦串是否回⽂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))dp[i][j] = i + 1 < j ? dp[i + 1][j - 1] : true;// 2. 枚举第⼆个字符串所有的起始位置和终⽌位置for (int i = 1; i < n - 1; i++)for (int j = i; j < n - 1; j++)if (dp[0][i - 1] && dp[i][j] && dp[j + 1][n - 1])return true;return false;}

四、分割回文串II

  1. 题目链接:分割回文串
  2. 题目描述:

给你⼀个字符串 s,请你将 s 分割成⼀些⼦串,使每个子串都是回文。 返回符合要求的最少分割次数 。
示例 1:输入:s = “aab” 输出:1
解释:只需⼀次分割就可将 s 分割成 [“aa”,“b”] 这样两个回⽂⼦串。
示例 2:输入:s = “a” 输出:0
示例 3:输入:s = “ab” 输出:1

  1. 解法(动态规划):
    算法思路:
    状态表⽰: 根据「经验」,继续尝试用 i 位置为结尾,定义状态表示,看看能否解决问题:
    dp[i] 表⽰: s 中 [0, i] 区间上的字符串,最少分割的次数。
    状态转移⽅程: 状态转移⽅程⼀般都是根据「最后⼀个位置」的信息来分析:设 0 <= j <= i ,那么我们可以 根据 j ~ i 位置上的⼦串是否是回⽂串分成下面两类:
    i. 当 [j ,i] 位置上的⼦串能够构成⼀个回文串,那么 dp[i] 就等于 [0, j - 1] 区 间上最少回文串的个数 + 1,即 dp[i] = dp[j - 1] + 1 ;
    ii. 当 [j ,i] 位置上的子串不能构成⼀个回文串,此时 j 位置就不用考虑。 由于我们要的是最⼩值,因此应该循环遍历⼀遍 j 的取值,拿到里面的最小值即可。 优化:我们在状态转移方程里面分析到,要能够快速判读字符串里面的子串是否回文。因此,我们 可以先处理⼀个 dp 表,里面保存所有子串是否回文的信息。
    初始化: 观察「状态转移方程」,我们会用到 j - 1 位置的值。我们可以思考⼀下当 j == 0 的时候, 表⽰的区间就是 [0, i] 。如果 [0, i] 区间上的字符串已经是回文串了,最⼩的回⽂串就是 1 了, j 往后的值就不⽤遍历了。 因此,我们可以在循环遍历 j 的值之前处理 j == 0 的情况,然后 j 从 1 开始循环。 但是,为了防止求 min 操作时, 0 干扰结果。我们先把表里面的值初始化为「无穷大」。
    填表顺序: 毫无疑问是「从左往右」。
    返回值: 根据「状态表示」,应该返回 dp[n - 1]

  2. 代码示例:

 public int minCut(String s) {// 1. 预处理int n = s.length();boolean[][] isPal = 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))isPal[i][j] = i + 1 < j ? isPal[i + 1][j - 1] : true;int[] dp = new int[n];for (int i = 0; i < n; i++) dp[i] = Integer.MAX_VALUE;for (int i = 0; i < n; i++) {if (isPal[0][i]) dp[i] = 0;else {for (int j = 1; j <= i; j++)if (isPal[j][i])dp[i] = Math.min(dp[i], dp[j - 1] + 1);}}return dp[n - 1];}

五、最长回文子序列

  1. 题目链接:最长回文子序列
  2. 题目描述:

给你⼀个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的⼀个序列。
示例 1:输入:s = “bbbab” 输出:4 解释:⼀个可能的最长回文子序列为 “bbbb” 。
示例 2:输入:s = “cbbd” 输出:2 解释:⼀个可能的最长回文子序列为 “bb” 。

  1. 解法(动态规划):
    算法思路:
    状态表示: 关于「单个字符串」问题中的「回文子序列」,或者「回文子串」,我们的状态表⽰研究的对象⼀ 般都是选取原字符串中的⼀段区域 [i, j] 内部的情况。这里我们继续选取字符串中的⼀段区域 来研究:
    dp[i][j] 表示:s 字符串 [i, j] 区间内的所有的⼦序列中,最长的回文子序列的长度。
    状态转移⽅程: 关于「回文子序列」和「回文子串」的分析方式,⼀般都是比较固定的,都是选择这段区域的「左 右端点」的字符情况来分析。因为如果⼀个序列示回文串的话,「去掉首尾两个元素之后依旧是回文串」,「⾸尾加上两个相同的元素之后也依旧是回文串」。因为,根据「首尾元素」的不同,可以分为下面两种情况:
    i. 当⾸尾两个元素「相同」的时候,也就是 s[i] == s[j] :那么 [i, j] 区间上的最长回文子序列,应该是 [i + 1, j - 1] 区间内的那个最长回文子序列首尾填上=s[i] 和 s[j] ,此时 dp[i][j] = dp[i + 1][j - 1] + 2
    ii. 当首尾两个元素不「相同」的时候,也就是 s[i] != s[j] :此时这两个元素就不能同 时添加在⼀个回文串的左右,那么我们就应该让 s[i] 单独加在⼀个序列的左边,或者 让 s[j] 单独放在⼀个序列的右边,看看这两种情况下的最大值:
    • 单独加入 s[i] 后的区间在 [i, j - 1] ,此时最长的回文序列的长度就是 dp[i]
    [j - 1] ;
    • 单独加⼊ s[j] 后的区间在 [i + 1, j] ,此时最长的回文序列的长度就是 dp[i + 1][j] ; 取两者的最⼤值,于是 dp[i][j] =max(dp[i][j - 1], dp[i + 1][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])
    初始化: 我们的初始化⼀般就是为了处理在状态转移的过程中,遇到的⼀些边界情况,因为我们需要根据状 态转移⽅程来分析哪些位置需要初始化。 根据状态转移⽅程 dp[i][j] = dp[i + 1][j - 1] + 2 ,我们状态表⽰的时候,选取的是⼀段区间,因此需要要求左端点的值要小于等于右端点的值,因此会有两种边界情况:
    i. 当 i == j 的时候, i + 1 就会大于 j - 1 ,此时区间内只有⼀个字符。这个比较好 分析, dp[i][j] 表示⼀个字符的最⻓回⽂序列,⼀个字符能够自己组成回文串,因此此
    时 dp[i][j] = 1 ;
    ii. 当 i + 1 == j 的时候, i + 1 也会大于 j - 1 ,此时区间内有两个字符。这样也好分析,当这两个字符相同的时候, dp[i][j] = 2 ;不相同的时候, d[i][j] = 0 。 对于第⼀种边界情况,我们在填表的时候,就可以同步处理。 对于第⼆种边界情况, dp[i + 1][j - 1] 的值为 0 ,不会影响最终的结果,因此可以不用考虑。
    填表顺序: 根据「状态转移」,我们发现,在 dp 表所表示的矩阵中, dp[i + 1] 表示下⼀行的位置,
    dp[j - 1] 表示前⼀列的位置。因此我们的填表顺序应该是「从下往上填写每⼀行」,「每⼀行从左往右」。
    这个与我们⼀般的填写顺序不太⼀致。
    返回值: 根据「状态表示」,我们需要返回 [0, n -1] 区域上的最长回文序列的长度,因此需要返回dp[0][n - 1] 。

  2. 代码示例:

public int longestPalindromeSubseq(String s) {// 1. 创建 dp 表// 2. 初始化// 3. 填表// 4. 返回结果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][j - 1], dp[i + 1][j]);}return dp[0][n - 1];}

六、让字符串成为回文串的最小插入次数

  1. 题目链接: 让字符串成为回文串的最小插入次数
  2. 题目描述:

给你⼀个字符串 s ,每⼀次操作你都可以在字符串的任意位置插⼊任意字符。 请你返回让 s 成为回⽂串的 最少操作次数 。 「回⽂串」是正读和反读都相同的字符串。
示例 1: 输⼊:s = “zzazz” 输出:0
解释:字符串 “zzazz” 已经是回⽂串了,所以不需要做任何插⼊操作。
示例 2: 输入:s = “mbadm” 输出:2 解释:字符串可变为 “mbdadbm” 或者 “mdbabdm” 。
示例 3: 输入:s = “leetcode”
输出:5 解释:插入 5 个字符后字符串变为 “leetcodocteel” 。 提⽰: 1 <= s.length <= 500
s 中所有字符都是小写字母。

  1. 解法(动态规划): 算法思路:
    状态表⽰: 关于「单个字符串」问题中的「回文子序列」,或者「回文子串」,我们的状态表⽰研究的对象⼀ 般都是选取原字符串中的⼀段区域 [i, j] 内部的情况。这里我们继续选取字符串中的⼀段区域来研究: 状态表示: dp[i][j] 表⽰字符串 [i, j] 区域成为回文子串的最少插入次数。
    状态转移方程: 关于「回文子序列」和「回文子串」的分析方式,⼀般都是比较固定的,都是选择这段区域的「左右端点」的字符情况来分析。因为如果⼀个序列是回文串的话,「去掉首尾两个元素之后依旧是回文串」,「首尾加上两个相同的元素之后也依旧是回文串」。因为,根据「首尾元素」的不同,可以分为下面两种情况:
    i. 当⾸尾两个元素「相同」的时候,也就是 s[i] == s[j] :
    那么 [i, j] 区间内成为回⽂⼦串的最少插入次数,取决于 [i + 1, j - 1] 区间 内成为回⽂⼦串的最少插入次数;
    若 i == j 或 i == j - 1 ( [i + 1, j - 1] 不构成合法区间),此时只有 1 ~ 2 个相同的字符, [i, j] 区间⼀定是回⽂⼦串,成为回⽂⼦串的最少插⼊次数是 0。 此时 dp[i][j] = i >= j - 1 ? 0 : dp[i + 1][j - 1] ;
    ii. 当⾸尾两个元素「不相同」的时候,也就是 s[i] != s[j] :
    此时可以在区间最右边补上⼀个 s[i] ,需要的最少插⼊次数是 [i + 1, j] 成为回文子串的最少插入次数 + 本次插⼊,即 dp[i][j] = dp[i + 1][j] + 1 ;
    此时可以在区间最左边补上⼀个 s[j] ,需要的最少插⼊次数是 [i, j + 1] 成为回文子串的最少插入次数 + 本次插⼊,即 dp[i][j] = dp[i][j + 1] + 1 ; 综上所述,状态转移⽅程为:
    ▪ 当 s[i] == s[j] 时: dp[i][j] = i >= j - 1 ? 1 : dp[i + 1][j - 1];
    ▪ 当 s[i] != s[j] 时: dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1 。
    初始化: 根据「状态转移方程」,没有不能递推表示的值。无需初始化。
    填表顺序: 根据「状态转移」,我们发现,在 dp 表所表示的矩阵中, dp[i + 1] 表示下一行的位置,
    dp[j - 1] 表示前⼀列的位置。因此我们的填表顺序应该是「从下往上填写每一行」,「每一行从左往右」。
    这个与我们⼀般的填写顺序不太⼀致。
    返回值: 根据「状态表示」,我们需要返回 [0, n -1] 区域上成为回文子串的最少插入次数,因此需要返回 dp[0][n - 1] 。

  2. 代码示例:

public int minInsertions(String s) {int n = s.length();int[][] dp = new int[n][n]; // 创建 dp 表for (int i = n - 1; i >= 0; i--)for (int j = i + 1; j < n; j++)if (s.charAt(i) == s.charAt(j)) dp[i][j] = dp[i + 1][j - 1];else dp[i][j] = Math.min(dp[i][j - 1], dp[i + 1][j]) + 1;return dp[0][n - 1];}

结语

本文到这里就结束了,主要通过几道回文子串算法题,介绍了这种类型动态规划的做题思路,带大家深入了解了动态规划中回文子串算法这一类型。

以上就是本文全部内容,感谢各位能够看到最后,如有问题,欢迎各位大佬在评论区指正,希望大家可以有所收获!创作不易,希望大家多多支持!

最后,大家再见!祝好!我们下期见!

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

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

相关文章

lodash库介绍(一个现代JavaScript实用工具库,提供模块化、性能优化和额外功能)JavaScript库(防抖、节流、函数柯里化)JS库

https://www.lodashjs.com/ 文章目录 Lodash库全解析简介核心优势一致性API模块化设计性能优化 常用功能分类数组操作对象操作函数增强 高级应用场景数据转换链函数组合 性能考量大数据集处理 最佳实践按需引入利用FP模块 结语 Lodash库全解析 简介 Lodash是一个现代JavaScri…

Spring MVC 国际化机制详解(MessageSource 接口体系)

Spring MVC 国际化机制详解&#xff08;MessageSource 接口体系&#xff09; 1. 核心接口与实现类详解 接口/类名描述功能特性适用场景MessageSource核心接口&#xff0c;定义消息解析能力支持参数化消息&#xff08;如{0}占位符&#xff09;所有国际化场景的基础接口Resource…

PyTorch张量范数计算终极指南:从基础到高阶实战

在深度学习领域&#xff0c;张量范数计算是模型正则化、梯度裁剪、特征归一化的核心技术。本文将以20代码实例&#xff0c;深度剖析torch.norm的9大核心用法&#xff0c;并揭示其在Transformer模型中的关键应用场景。 &#x1f680; 快速入门&#xff08;5分钟掌握核心操作&…

荣耀90 GT信息

外观设计 屏幕&#xff1a;采用 6.7 英寸 AMOLED 荣耀绿洲护眼屏&#xff0c;超窄边框设计&#xff0c;其上边框 1.6mm&#xff0c;左右黑边 1.25mm&#xff0c;屏占较高&#xff0c;带来更广阔的视觉体验。屏幕还支持 120Hz 自由刷新率&#xff0c;可根据使用场景自动切换刷新…

【Java中级】11章、枚举 - java引用数据类型,枚举介绍、快速入门,了解枚举类的基本使用方式【1】

文章内容&#xff1a; 自定义实现枚举enum关键字实现枚举 ❤️内容涉及枚举的定义&#xff0c;快速入门&#xff0c;注意事项和小题巩固知识点 &#x1f308; 跟着B站一位老师学习的内部类内容&#xff0c;现写这篇文章为学习内部类的小伙伴提供思路支持&#xff0c;希望可以一…

局域网访问 Redis 方法

局域网访问 Redis 方法 默认情况下&#xff0c;Redis 只允许本机 (127.0.0.1) 访问。如果你想让局域网中的其他设备访问 Redis&#xff0c;需要 修改 Redis 配置&#xff0c;并确保 防火墙放行端口。 方法 1&#xff1a;修改 Redis 配置 1. 修改 redis.conf&#xff08;或 me…

如何应对客户频繁变更需求

如何应对客户频繁变更需求&#xff1f;要点包括&#xff1a; 快速响应、深入沟通、灵活规划、过程记录、风险管控。这些策略既能降低项目失控风险&#xff0c;也能帮助团队在变动环境中保持高效率。其中深入沟通尤为关键&#xff0c;它不仅能够让团队第一时间了解客户意图&…

Set 集合

默认情况下&#xff0c; Scala 使用的是不可变集合&#xff0c; 如果你想使用可变集合&#xff0c; 需要引用 scala.collection.mutable.Set Set 默认是不可变集合&#xff0c;数据无序 数据不可重复 遍历集合 创建可变集合 mutable.Set 打印集合 集合添加元素 向集合中…

最新 OpenHarmony 系统一二级目录整理

我们在学习 OpenHarmony 的时候&#xff0c;如果对系统的目录结构了解&#xff0c;那么无疑会提升自己对 OpenHarmony 更深层次的认识。 于是就有了今天的整理。 首先在此之前&#xff0c;我们要获取源码 获取源码的方式 OpenHarmony 主干代码获取 方式一&#xff08;推荐&am…

STL常用容器整理

STL常用容器操作整理 STL常用容器操作整理&#xff08;string/vector/set/map&#xff09;一、string&#xff08;字符串&#xff09;构造函数元素访问修改操作容量操作子串与查找 二、vector&#xff08;动态数组&#xff09;构造函数元素访问修改操作容量操作 三、set&#x…

Unity 实现伤害跳字

核心组件&#xff1a; Dotween TextMeshPro 过程轨迹如下图&#xff1a; 代码如下&#xff1a; using System.Collections; using System.Collections.Generic; using DG.Tweening; using TMPro; using UnityEngine; using UnityEngine.Pool;public class …

Ubuntu 22.04 AI大模型环境配置及常用工具安装

一、基础环境准备 1.1 系统准备 建议使用 Ubuntu22.04 以下配置皆以 Ubuntu22.04 系统版本为例 1.2 安装git apt-get update && apt-get install git -y1.3 安装 Python 3.9 【建议安装 3.10】&#xff08;安装miniconda或者conda来管理虚拟环境&#xff09; wget …

STM32单片机入门学习——第27节: [9-3] USART串口发送串口发送+接收

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难&#xff0c;但我还是想去做&#xff01; 本文写于&#xff1a;2025.04.08 STM32开发板学习——第27节: [9-3] USART串口发送&串口发送接收 前言开发板说…

前端实现docx格式word文件预览,可以兼容原生、vue2、以及uni-app 项目,详细步骤。

上一篇记录了PDF文件预览功能。这一篇记录下docx文件预览。 核心文件 doc.html <script src"./build/polyfill.min.js"></script> <script src"./build/jszip.min.js"></script> <script src"./build/docx-preview.js&…

Java中的ArrayList方法

1. 创建 ArrayList 实例 你可以通过多种方式创建 ArrayList 实例&#xff1a; <JAVA> ArrayList<String> list new ArrayList<>(); // 创建一个空的 ArrayList ArrayList<String> list new ArrayList<>(10); // 创建容量为 10 的 ArrayList …

【anaconda下py】

38 https://repo.anaconda.com/archive/Anaconda3-2020.11-Windows-x86.exe 39 https://repo.anaconda.com/archive/Anaconda3-2022.10-Windows-x86_64.exe 310https://repo.anaconda.com/archive/Anaconda3-2023.03-0-Windows-x86_64.exe 历史列表Index of /archive 远程&…

linux--------------进程控制(下)

一、进程等待 1.1 进程等待必要性 子进程退出后&#xff0c;若父进程不管不顾&#xff0c;可能会产生 “僵尸进程”&#xff0c;进而造成内存泄漏。进程一旦变为僵尸状态&#xff0c;即使使用 kill -9 也无法将其杀死&#xff0c;因为无法杀死一个已死的进程。父进程需要了解…

docker 中跑faster-whisper 教程(1050显卡)

之前我本地机器运行faster-whisper 会报错类似 Could not load library libcudnn_ops_infer.so.8github 上也有类似的情况 &#xff1a;https://github.com/SYSTRAN/faster-whisper/issues/516#issuecomment-2785038635 缺少.so.8 文件&#xff0c;我通过以下方式&#xff0c;…

人大金仓数据库dum文件进行备份数据和恢复数据

逻辑备份命令: sys_dump -U SYSTEM -d problem_dev -Fc -f /db_backup/kingbase/dump/problem_dev/problem_dev20240329.dmp用户:SYSTEM 数据库名:problem_dev 格式:自定义格式(-Fc) 输出文件:/db_backup/kingbase/dump/problem_dev/problem_dev20240329.dmp sys_dump…

Java的Selenium元素定位-xpath

xpath其实就是一个path(路径)&#xff0c;一个描述页面元素位置信息的路径&#xff0c;相当于元素的坐标xpath基于XML文档树状结构&#xff0c;是XML路径语言&#xff0c;用来查询xml文档中的节点。 绝对定位 从根开始找--/(根目录)/html/body/div[2]/div/form/div[5]/button缺…