动态规划——回文串问题

news2024/11/24 13:08:10

目录

练习1:回文子串

练习2:最长回文子串

练习3:回文串分割IV

练习4:分割回文串

练习5:最长回文子序列

练习6:让字符串成为回文串的最小插入次数


本篇文章主要学习使用动态规划来解决回文串相关问题,我们通过相关练习来学习

练习1:回文子串

题目链接:

647. 回文子串 - 力扣(LeetCode)

题目描述:

给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

回文字符串 是正着读和倒过来读一样的字符串。

子字符串 是字符串中的由连续字符组成的一个序列。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

示例 1:

输入:s = "abc"
输出:3
解释:三个回文子串: "a", "b", "c"

示例 2:

输入:s = "aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"

提示:

  • 1 <= s.length <= 1000
  • s 由小写英文字母组成

思路分析:

 题目要求我们统计字符串中 回文子串 的数目,其中,具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。如例2所示:

选择前两个位置的字符,形成子串 "aa",选择后两个位置的字符,形成子串"aa",这两个子串虽然字符相同,但其开始 和 结束位置不同,因此,视作不同的子串

子串:字符串中的由连续字符组成的一个序列。

我们来分析状态表示

状态表示:

要统计字符串中回文子串的个数,就是要判断字符串的所有子串是否回文,如何判断呢?

要判断子串是否是回文,首先要找到所有子串,

表示出所有子串

我们以 i 位置作为子串的起始位置,j 位置作为子串的结束位置

我们固定 i 位置,然后向后移动 j 位置,就可以枚举出 以 i 位置为起始的所有子串

然后向后移动 i,继续向后枚举

因此,我们使用两层 for 循环,就可以枚举出字符串的所有子串,也就是说,我们用 一个二维数组就可以表示出所有情况 

我们以横坐标作为子串的起始位置,纵坐标作为子串的结束位置

dp[i][j]:以 i 位置为起始,j 位置为结束的子串

由于起始位置 <= 结束位置,因此,我们只需要使用dp表中右上三角部分的空间就可以表示出所有子串

接下来,我们判断子串是否是回文串

判断子串是否是回文串 

我们已经使用二维dp表表示出了所有情况,因此,我们只需要想办法在对应[i, j]位置上填上 true 或 false,就可以表示以 i 位置为起始,j位置为结束的字符是否是回文串了

因此,dp[i][j]:以 i 位置为起始,j位置为结束的子串是否是回文串

状态转移方程:  

要判断子串(从i位置到j位置)是否是回文串,首先要判断两端点(s[i] == s[j])是否相同,

若两端的字符都不相同,则子串一定不是回文串

若两端点相同,我们还需分情况讨论:

若 i = j,则该子串只有一个字符,一定是回文串,dp[i][j] = true

若 i + 1 = j,该子串有两个字符且相同,一定是回文串,dp[i][j] = true

若 i + 1 < j,则该子串有多个字符,我们已经判断出两端点的字符相同,接下来,我们需要判断 [i+1, j-1]区间内的字符是否相同,即判断以 i + 1位置为起始,j - 1位置为结束的子串是否是回文串

而 dp[i+1][j-1] 表示 以 i + 1位置为起始,j - 1位置的子串是否是回文串,因此 dp[i][j] = dp[i+1][j-1]

因此,状态转移方程为:

初始化:

初始化要保证填表时不越界,但在填写dp表时,不会发生越界,因此我们无需初始化

填表顺序:

当 s[i] = s[j] 且 i + 1 < j 时,dp[i][j] = dp[i+1][j-1] 

因此,在填写 [i][j]位置时要保证[i+1][j-1]位置已经填写,因此,需要从下往上填写,而在填写每一行时,从左往右或从右往左都可以

返回值:

 要求回文子串的个数,因此,要返回 dp 表中 true 的个数

代码实现:

class Solution {
    public int countSubstrings(String s) {
        int n = s.length();
        int ret = 0;//统计回文子串的个数
        //创建dp表
        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(i == j || i + 1 == j) dp[i][j] = true;
                    else dp[i][j] = dp[i + 1][j - 1];
                }
                if(dp[i][j]) ret++;
            }
        }
        //返回
        return ret;
    }
}

练习2:最长回文子串

题目链接:

5. 最长回文子串 - 力扣(LeetCode)

题目描述:

给你一个字符串 s,找到 s 中最长的回文子串。

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"
输出:"bb"

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母组成

思路分析:

题目要求我们找到字符串中的最长回文子串。因此,我们首先要判断子串是否是回文串,然后再找到其中最长的回文子串

本题的解题思路与 练习1:回文子串 类似

我们可以使用二维dp表表示出所有情况,判断出所有子串是否为回文串

若 dp[i][j] = true,则以 i 位置为起始,j 位置为结尾的子串是回文串,其长度为 j - i + 1

因此,我们只需找到回文子串中 j - i + 1 的最大值,即可找到最长的回文子串

代码实现:

class Solution {
    public String longestPalindrome(String s) {
        int n = s.length();
        int begin = 0, len = 1;//记录最长子串的起始位置和长度
        //创建dp表
        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;
                }
                if(dp[i][j] && j - i + 1 > len){
                    len = j - i + 1;
                    begin = i;
                }
            }
        }
        //返回
        return s.substring(begin, begin + len);
    }
}

练习3:回文串分割IV

题目链接:

1745. 分割回文串 IV - 力扣(LeetCode)

题目描述:

给你一个字符串 s ,如果可以将它分割成三个 非空 回文子字符串,那么返回 true ,否则返回 false 。

当一个字符串正着读和反着读是一模一样的,就称其为 回文字符串 。

示例 1:

输入:s = "abcbdd"
输出:true
解释:"abcbdd" = "a" + "bcb" + "dd",三个子字符串都是回文的。

示例 2:

输入:s = "bcbddxy"
输出:false
解释:s 没办法被分割成 3 个回文子字符串。

提示:

  • 3 <= s.length <= 2000
  • s​​​​​​ 只包含小写英文字母。

思路分析:

 将字符串分割成三个非空字符串,若分割后三个子串都是回文串,则返回true,不能分割,则返回false

设中间字符串的起始位置为 i,结束位置为 j

则划分后三个子串的区间分别为:[0, i - 1] [i, j] [j + 1, n-1]

此时,我们需要判断三个子串是否是回文串

同样的,我们可以使用二维dp表表示出所有情况,判断出所有子串是否为回文串

此时,判断这三个子串是否是回文串就变得非常简单了,只需判断 dp[0][i - 1]、dp[i, j] 和 dp[j + 1][n - 1] 是否都为true,就可以判断出这三个子串是否都是回文串了

因此,只需先判断所有子串是否是回文串,然后枚举第二个字符串所有的起始位置和结束位置,查询这三段非空子串是否是回文串即可

代码实现:

class Solution {
    public boolean checkPartitioning(String s) {
        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;
            }
        }
        //枚举第二个字符串的所有起始位置和结束位置
        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;
    }
}

练习4:分割回文串

题目链接:

132. 分割回文串 II - 力扣(LeetCode)

题目描述:

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文串。

返回符合要求的 最少分割次数 。

示例 1:

输入:s = "aab"
输出:1
解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。

示例 2:

输入:s = "a"
输出:0

示例 3:

输入:s = "ab"
输出:1

提示:

  • 1 <= s.length <= 2000
  • s 仅由小写英文字母组成

思路分析:

要求将字符串分割成子串的最少分割次数

状态表示:

我们首先以 i 位置为结尾进行分析:

dp[i]: [0, i]区间内的最少分割次数

状态转移方程:

若 以 0 位置为起始,i位置为结尾的子串是回文串,此时不需要分割,dp[i] = 0

而  以 0 位置为起始,i位置为结尾的子串不是回文串时,我们根据前面的状态来推导 dp[i]

假设我们在 j 位置进行分割,则分割出 以 j 位置为起始,i 位置为结尾的子串,若这个子串是回文串

则 我们只需要考虑 [0, j - 1]区间内分割了多少词(dp[j - 1]),再加上这一次,就可以 得到 dp[i]

因此,我们先考虑最后一次分割:

假设在 j 位置进行分割(0 < j <= i),然后判断 从 j 到 i 这个子串是否是回文串:

若 是 回文串,则 dp[i] = dp[j - 1] + 1

若 不是 回文串,此时这种分割方式不合理,不考虑

我们要求最小分割次数,因此 我们要求能够分割的情况中的最小值(即min(dp[j - 1] + 1))

在此过程中,我们需要判断 [0, i ] 区间子串是否是回文,[j, i]区间子串是否是回文,因此,我们同样可以使用 二维dp表,判断所有子串是否是回文串

初始化:

 初始化要保证填表时不越界,当 j = 0时可能会越界,但 j 不可能为 0,因此不会发生越界,但由于我们要求 dp[i]的最小值,因此我们可以将所有的值都初始化为最大值

填表顺序:

填写 dp[i] 时,要保证 dp[j - 1]已经填写,j - 1 在 i 位置之前,因此 填表顺序为从左到右 

返回值:

dp[i] :0 到 i 位置的最小分割次数,要求字符串的最小分割次数,因此返回 dp[n - 1] 

代码实现:

class Solution {
    public int minCut(String s) {
        //预处理
        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;
            }
        }
        //创建dp表
        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];
    }
}

练习5:最长回文子序列

题目链接:

516. 最长回文子序列 - 力扣(LeetCode)

题目描述:

给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

示例 1:

输入:s = "bbbab"
输出:4
解释:一个可能的最长回文子序列为 "bbbb" 。

示例 2:

输入:s = "cbbd"
输出:2
解释:一个可能的最长回文子序列为 "bb" 。

提示:

  • 1 <= s.length <= 1000
  • s 仅由小写英文字母组成

思路分析:

本题与前面的题不同,要求的是最长回文序列子串,是连续的字符串,而子序列,可以是连续的,也可以是不连续的,是在不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

状态表示:

我们首先以 i 位置为结尾进行分析,则 dp[i]:以 i 位置为结尾的所有子序列中,最长的回文子序列的长度

接着,我们来分析状态转移方程:

我们需要根据前面的状态来推导dp[i],我们以 i - 1位置进行分析,但是 dp[i - 1] :以 i 位置为结尾的所有子序列中,最长的回文子序列的长度,我们不知道回文子序列是怎样的,不能确定添加s[i]后是否依旧是回文子序列,因此无法确定dp[i]

我们再考虑其他方法

若 以 i 位置为起始,j 位置为结尾的子串是回文串,在这个子串的左右加上相同的字符,新的子串依旧是回文串

则,若[i + 1, j - 1]内存在最长回文子序列,则

若s[i] == s[j],则最长回文子序列长度 + 2,则[i, j]区间内的最长回文子序列长度 = [i + 1, j - 1]区间内最长回文子序列长度 + 2,因此我们可以根据[i+1, j - 1]区间内的最长回文子序列长度,推导出[i, j]区间内最长回文子序列的长度

我们根据这个思路来定义状态表示:

dp[i][j]:字符串[i, j]区间内的最长回文子序列长度

接下来,我们分析状态转移方程

状态转移方程:

我们以 i 位置为起始,j 位置为结束 

若 s[i] = s[j],则 dp[i][j] = dp[i + 1][j - 1] + 1,但前提条件是dp[i + 1][j - 1]存在,因此,我们需要分情况讨论:

若 i = j,则[i, j]区间内只有一个字符,则 最长回文子序列长度为 1

若 i + 1 = j,则[i, j]区间内有两个相同的字符,则 最长回文子序列长度为 2

若 i + 1 < j,则[i, j]区间内有多个字符,则只需要在[i + 1, j - 1]区间内找到最长回文子序列长度,然后再 + 2,即 dp[i + 1][j - 1] + 2

若 s[i] != s[j],则最长回文子序列一定不可能 以 i 位置为起始,以 j 位置为结束,因此,我们可以在[i, j - 1]内找最长回文子序列长度,然后在[i + 1, j]区间内找最长回文子序列长度,最后取其中的较大值,即 max(dp[i, j - 1], dp[i + 1, j])

因此,状态转移方程为:

初始化:

由于在填表时不会发生越界,因此无需初始化

填表顺序:

 由于 i <= j,因此只会填写:

在填写dp[i][j]时,需要 dp[i + 1][j - 1]、dp[i][j - 1] 和 dp[i - 1][j]

因此,我们首先要保证从下往上填写,在填写时需要用到左边的值,因此在填写每一行时,要从左往右填写 

返回值:

dp[i][j]: 字符串[i, j]区间内的最长回文子序列长度,而需要求字符串的最长回文子序列长度,即起始位置为0,结束位置为 n - 1,因此,返回dp[0][n - 1]

代码实现:

class Solution {
    public int longestPalindromeSubseq(String s) {
        int n = s.length();
        //创建dp表
        int[][] dp = new int[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(i == j) dp[i][j] = 1;
                    else if(i + 1 == j) dp[i][j] = 2;
                    else 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];
    }
}

练习6:让字符串成为回文串的最小插入次数

题目链接:

1312. 让字符串成为回文串的最少插入次数 - 力扣(LeetCode)

题目描述:

给你一个字符串 s ,每一次操作你都可以在字符串的任意位置插入任意字符。

请你返回让 s 成为回文串的 最少操作次数 。

「回文串」是正读和反读都相同的字符串。

示例 1:

输入:s = "zzazz"
输出:0
解释:字符串 "zzazz" 已经是回文串了,所以不需要做任何插入操作。

示例 2:

输入:s = "mbadm"
输出:2
解释:字符串可变为 "mbdadbm" 或者 "mdbabdm" 。

示例 3:

输入:s = "leetcode"
输出:5
解释:插入 5 个字符后字符串变为 "leetcodocteel" 。

提示:

  • 1 <= s.length <= 500
  • s 中所有字符都是小写字母。

思路分析:

题目要求我们在字符串中插入字符使其成为回文串,要求出最少插入次数 

状态表示:

练习5:最长回文子序列 类似,当我们选择以 i 位置为结尾时,很难推出状态转移方程,因此,我们以 [i, j]区间来研究问题(i <= j)

dp[i][j]:[i, j]区间内,使其成为回文串的最小插入次数

状态转移方程:

我们根据最后一步来划分问题,也就是根据两个端点(i,j)来划分问题:

若 s[i] = s[j]:

若 i = j,则[i, j]区间内只有一个字符,此时已经是回文串了,插入次数为0

若 i + 1 = j,则[i, j]区间内有两个字符相同的字符,此时也是回文串了,插入次数为 0

若 i + 1  < j,则[i, j]区间内有多个字符,由于s[i] = s[j],因此两端字符不用考虑,只需考虑[i + 1, j - 1]区间内的最小插入次数,即 dp[i + 1][j - 1]

若 s[i] != s[j]:

此时我们在[i, j]区间的最左边添加上字符s[j],就可以与 最右边的s[j]匹配,此时,我们只需考虑[i, j - 1]区间内的最小操作次数,即 dp[i][j - 1],然后再加上此时添加的一个字符,即 dp[i][j - 1] + 1

同样的,在最右边添加上字符s[i],就可以和最左边的s[i]匹配,此时只需考虑[i + 1, j]区间内的最小操作次数,即 dp[i + 1][j],然后再加上此时添加的一个字符,即 dp[i + 1][j] + 1

要最小操作次数,只需取最小值,min(dp[i + 1][j] + 1, dp[i][j - 1] + 1)

因此,状态转移方程为:

初始化: 由于在填表时不会发生越界,因此无需初始化

填表顺序:

在填写dp[i][j]时,需要 dp[i + 1][j - 1]、dp[i][j - 1] 和 dp[i - 1][j]

因此,我们首先要保证从下往上填写,在填写时需要用到左边的值,因此在填写每一行时,要从左往右填写 

返回值:

dp[i][j]:[i, j]区间内,使其成为回文串的最小插入次数,而需要求字符串成为回文串的最少插入次数,即起始位置为0,结束位置为 n - 1,因此,返回dp[0][n - 1]

代码实现:

class Solution {
    public int minInsertions(String s) {
        int n = s.length();
        //创建dp表
        int[][] dp = new int[n][n];
        //填表
        for(int i = n-1; i >= 0; i--){
            for(int j = i + 1; j < n; j++){//i = j的时候,dp[i][j] = 0,因此无需再考虑
                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] + 1, dp[i + 1][j] + 1);
                }
            }
        }
        //返回
        return dp[0][n - 1];
    }
}

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

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

相关文章

【C#】知识点速通

前言&#xff1a; 笔者是跟着哔站课程&#xff08;Trigger&#xff09;学习unity才去学习的C#&#xff0c;并且C语言功底尚存&#xff0c;所以只是简单地跟着课程将unity所用的C#语言的关键部分进行了了解&#xff0c;然后在后期unity学习过程中加以深度学习。如需完善的C#知识…

JDBC远程连接mysql报错:NotBefore: Sat Mar 30 16:37:41 UTC 2024

虚拟机docker已经部署了mysql&#xff0c;用navicat可以直接远程连接&#xff0c;datagrip却不能&#xff0c;如图&#xff1a; 需要在最后加上 ?useSSLfalse , 如&#xff1a;jdbc:mysql://192.168.30.128:3306?useSSLfalse navicat不用加的原因是没有使用jdbc连接&#x…

实验二 pandas库绘图以及数据清洗

1.1pandas验证操作 1、验证以下代码&#xff0c;并将结果附截图 import pandas as pd A[1,3,6,4,9,10,15] weight[67,66,83,68,79,88] sex[女,男,男,女,男, 男] S1pd.Series(A)#构建S1序列 print(S1) S2pd.Series(weight)#构建S2序列 print(S2) S3pd.Series(sex)#构建S3序列 p…

第3章.引导ChatGPT精准角色扮演:高效输出专业内容

角色提示技术 角色提示技术&#xff08;role prompting technique&#xff09;&#xff0c;是通过模型扮演特定角色来产出文本的一种方法。用户为模型设定一个明确的角色&#xff0c;它就能更精准地生成符合特定上下文或听众需求的内容。 比如&#xff0c;想生成客户服务的回复…

STM32的DMA

DMA(Direct memory access)直接存储器存取,用来提供在外设和存储器之间或者存储 器和存储器之间的高速数据传输&#xff0c;无须CPU干预&#xff0c;数据可以通过DMA快速地移动&#xff0c;这就节 省了CPU的资源来做其他操作。 STM32有两个DMA控制器共12个通道(DMA1有7个通道…

(八)目标跟踪中参数估计(似然、贝叶斯估计)理论知识

目录 前言 一、统计学基础知识 &#xff08;一&#xff09;随机变量 &#xff08;二&#xff09;全概率公式 &#xff08;三&#xff09;高斯分布及其性质 二、似然是什么&#xff1f; &#xff08;一&#xff09;概率和似然 &#xff08;二&#xff09;极大似然估计 …

Linux内核之Binder驱动container_of进阶用法(三十四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

EasyRecovery2024汉化精简版,无需注册

EasyRecovery2024是世界著名数据恢复公司 Ontrack 的技术杰作&#xff0c;它是一个威力非常强大的硬盘数据恢复软件。能够帮你恢复丢失的数据以及重建文件系统。 EasyRecovery不会向你的原始驱动器写入任何东东&#xff0c;它主要是在内存中重建文件分区表使数据能够安全地传输…

ctfshow web入门 XXE

XXE基础知识 XXE&#xff08;XML External Entity&#xff09;攻击是一种针对XML处理漏洞的网络安全攻击手段。攻击者利用应用程序在解析XML输入时的漏洞&#xff0c;构造恶意的XML数据&#xff0c;进而实现各种恶意目的。 所以要学习xxe就需要了解xml xml相关&#xff1a; …

Chrome浏览器 安装Vue插件vue-devtools

前言 vue-devtools 是一个为 Vue.js 开发者设计的 Chrome 插件。它可以让你更轻松地审查和调试 Vue 应用程序。与普通的浏览器控制台工具不同&#xff0c;Vue.js devtools 专为 Vue 的响应性数据和组件结构量身定做。 1. 功能介绍 组件树浏览&#xff1a;这个功能可以让你查…

使用Python实现ID3决策树中特征选择的先后顺序,字节跳动面试真题

def empty1(pri_data): hair [] #[‘长’, ‘短’, ‘短’, ‘长’, ‘短’, ‘短’, ‘长’, ‘长’] voice [] #[‘粗’, ‘粗’, ‘粗’, ‘细’, ‘细’, ‘粗’, ‘粗’, ‘粗’] sex [] #[‘男’, ‘男’, ‘男’, ‘女’, ‘女’, ‘女’, ‘女’, ‘女’] for o…

OpenHarmony error: signature verification failed due to not trusted app source

问题&#xff1a;error: signature verification failed due to not trusted app source 今天在做OpenHarmony App开发&#xff0c;之前一直用的设备A在测试开效果&#xff0c;今天换成了设备B&#xff0c;通过DevEco Studio安装应用程序的时候&#xff0c;就出现错误&#xf…

爱上数据结构:栈和队列的概念及使用

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;数据结构 ​ 一、栈 1.栈的基本概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶&#xff0c;…

不同Python版本和wxPython版本用pyinstaller打包文件大小对比

1、确定wxPython和Python版本的对应关系 在这里可以找到Python支持的所有wxPython版本&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple/wxpython/ 由于Python从3.6版本开始支持f字符串、从3.9版本开始不支持Windows7操作系统&#xff0c;所以我仅筛选3.6-3.8之间的版本…

qupath再度更新:使用WSInfer进行深度学习

Open and reusable deep learning for pathology with WSInfer and QuPath Open and reusable deep learning for pathology with WSInfer and QuPath | npj Precision Oncology (nature.com) 以前&#xff1a;数字病理图像分析的开源软件qupath学习 ①-CSDN博客 背景 深度学…

HarmonyOS实战开发-如何实现一个自定义抽奖圆形转盘

介绍 本篇Codelab是基于画布组件、显式动画&#xff0c;实现的一个自定义抽奖圆形转盘。包含如下功能&#xff1a; 通过画布组件Canvas&#xff0c;画出抽奖圆形转盘。通过显式动画启动抽奖功能。通过自定义弹窗弹出抽中的奖品。 相关概念 Stack组件&#xff1a;堆叠容器&am…

统计XML文件内标签的种类和其数量及将xml格式转换为yolov5所需的txt格式

1、统计XML文件内标签的种类和其数量 对于自己标注的数据集&#xff0c;需在标注完成后需要对标注好的XML文件校验&#xff0c;下面是代码&#xff0c;只需将SrcDir换成需要统计的xml的文件夹即可。 import os from tqdm import tqdm import xml.dom.minidomdef ReadXml(File…

Day62-Nginx四层负载均衡及结合7层负载均衡实践

Day62-Nginx四层负载均衡及结合7层负载均衡实践 1. 什么是四层负载均衡&#xff1f;2. 四层负载均衡的常用场景3. 百万并发百亿PV大规模架构4. L4和L7的区别及常用软件。5. lvs、nginx、haproxy区别6. nginx四层负载均衡&#xff08;tcp/ip&#xff0c;ip:port&#xff09;7. n…

python多方式操作elasticsearch介绍

python多方式操作elasticsearch介绍 1. requests模块操作ES ​ requests 是一个 Python HTTP 库&#xff0c;它简化了发送 HTTP 请求和处理响应的过程。通过 requests 模块&#xff0c;开发人员可以轻松地与 Web 服务进行通信&#xff0c;包括获取网页内容、执行 API 请求等。…

JavaScript(一)---【js的两种导入方式、全局作用域、函数作用域、块作用域】

一.JavaScript介绍 1.1什么是JavaScript JavaScript简称“js”&#xff0c;js与java没有任何关系。 js是一种“轻量级、解释型、面向对象的脚本语言”。 二.JavaScript的两种导入方式 2.1内联式 在HTML文档中使用<script>标签直接引用。 <script>console.log…