1177.构建回文窜检测

该问题涉及字符串处理,算法设计。给定一个字符串s和一系列查询,每个查询包含一个子串范围及可替换的最大字母数k。目标是检查能否通过最多k次替换将子串变成回文。解决方案是计算每个位置奇数次出现的字符数量,然后在查询时比较可替换次数是否足以平衡子串的奇偶性差异。

题目描述:

给你一个字符串 s,请你对 s 的子串进行检测。
每次检测,待检子串都可以表示为 queries[i] = [left, right, k]。我们可以 重新排列 子串 s[left], …, s[right],并从中选择 最多 k 项替换成任何小写英文字母。
如果在上述检测过程中,子串可以变成回文形式的字符串,那么检测结果为 true,否则结果为 false。
返回答案数组 answer[],其中 answer[i] 是第 i 个待检子串 queries[i] 的检测结果。
注意:在替换时,子串中的每个字母都必须作为 独立的 项进行计数,也就是说,如果 s[left…right] = “aaa” 且 k = 2,我们只能替换其中的两个字母。(另外,任何检测都不会修改原始字符串 s,可以认为每次检测都是独立的)

示例:

来源:力扣(LeetCode)

解题思路:

使用数组存储第i步是字符串中存在奇数次的字符–》循环计算第x步的字符串中存在奇数次的字符的和–》可替换次数大于总和的一半,即可完成对字符串的更改。

代码附上:

class Solution {
    public List<Boolean> canMakePaliQueries(String s, int[][] queries) {
        List<Boolean> list=new ArrayList<>();
        char[] f=s.toCharArray();
        int[][] sum=new int[f.length+1][26];
        int count=0,x=1;
        for(int i=0;i<f.length;i++) {
            for(int j=0;j<26;j++) {
                sum[x][j]=sum[x-1][j];
            }
            if(sum[x-1][f[i]-97]==0) sum[x][f[i]-97]++;
            else sum[x][f[i]-97]--;
            x++;
        }
        for(int i=0;i<queries.length;i++) {
            count=0;
            for(int j=0;j<26;j++) {
                if(sum[queries[i][1]+1][j]-sum[queries[i][0]][j]!=0) count++;
            }
            list.add(count/2<=queries[i][2]);
        }
        return list;
    }
}
### Java 分割回文算法实现 以下是基于回溯法的 `Java` 实现,用于解决分割回文串问题。该方法通过递归遍历所有可能的子串组合,并利用动态规划优化判断回文的过程。 #### 动态规划预处理 为了提高效率,在递归之前先构建一个二维布尔数组 `dp` 来记录字符串中的任意区间 `[i, j]` 是否为回文串。这样可以在后续的递归过程中快速查询某个子串是否满足条件[^1]。 ```java class Solution { boolean[][] dp; List<List<String>> result = new ArrayList<>(); public List<List<String>> partition(String s) { int n = s.length(); dp = new boolean[n][n]; // 预处理 dp 数组 for (int i = n - 1; i >= 0; i--) { for (int j = i; j < n; j++) { if (s.charAt(i) == s.charAt(j) && (j - i <= 2 || dp[i + 1][j - 1])) { dp[i][j] = true; } } } backtrack(s, 0, new ArrayList<>()); return result; } private void backtrack(String s, int start, List<String> currentList) { if (start == s.length()) { result.add(new ArrayList<>(currentList)); return; } for (int end = start; end < s.length(); end++) { if (!dp[start][end]) continue; // 如果当前子串是回文,则加入路径并继续递归 currentList.add(s.substring(start, end + 1)); backtrack(s, end + 1, currentList); // 回溯操作 currentList.remove(currentList.size() - 1); } } } ``` #### 算法说明 1. **初始化 DP 数组** 使用双层循环填充 `dp` 数组,其中 `dp[i][j]` 表示字符串从索引 `i` 到 `j` 的子串是否为回文串。如果两端字符相等且内部部分也是回文(即 `dp[i+1][j-1]==true`),则标记为真[^3]。 2. **回溯函数设计** 定义了一个辅助函数 `backtrack` 进行递归调用。每次尝试将当前位置到某终点之间的子串作为候选者,当确认其为回文时才将其添加至临时列表中,并进一步探索剩余部分[^4]。 3. **终止条件** 当起始位置等于字符串长度时,表示已经完成了一种合法划分方式,此时需保存当前的结果副本[^2]。 --- ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值