【每日一题Day238】LC1177构建回文串检测 | 前缀和 + 异或

简介: 【每日一题Day238】LC1177构建回文串检测 | 前缀和 + 异或

构建回文串检测【LC1177】

给你一个字符串 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,可以认为每次检测都是独立的)

类似题目

前缀和
  • 思路
    由于可以将子串重新排列,那么重新排列后能否构成回文串取决于子串中奇数个字母的数目num
  • 偶数个字母可以在回文串头尾各放一个,因此可以忽略
  • 将个数为奇数的字母一半替换成其他字母,如果num为奇数,剩余的一个可以放在中间,那么需要替换num/2个字母如果暴力求出子串中奇数个字母的数目,时间复杂度为O ( n 2 ) 会超时,优化思路为使用前缀和数组预处理每个字母的数量,那么能快算求出子串中奇数个字母的数目
  • 实现
class Solution {
    public List<Boolean> canMakePaliQueries(String s, int[][] queries) {
        // 怎么快速求出子串中每种字母的个数?
        // 前缀和:存储每个字母在字符串[0,i]中出现的个数
        int n = s.length();
        int[][] count = new int[n + 1][26];
        for (int i = 0; i < n; i++){
            for (int j = 0; j < 26; j++){
                count[i + 1][j] = count[i][j];
                if (j == s.charAt(i) - 'a'){
                    count[i + 1][j]++;
                }
            }
        }
        List<Boolean> res = new ArrayList<>();
        for (int[] q : queries){
            int l = q[0], r = q[1], k = q[2];
            int num = 0;
            for (int i = 0; i < 26; i++){
                if ((count[r + 1][i] - count[l][i]) % 2 == 1){
                    num++;
                }
            }
            if (num / 2 <= k){
                res.add(true);
            }else{
                res.add(false);
            }
        }
        return res;
    }
}

复杂度

  • 时间复杂度:O((n+q)C)
  • 空间复杂度:O ( n C )
目录
相关文章
|
6月前
【每日一题Day369】LC187重复的DNA序列 | 字符串哈希
【每日一题Day369】LC187重复的DNA序列 | 字符串哈希
45 1
|
6月前
【每日一题Day150】LC1616分割两个字符串得到回文串 | 双指针+贪心
【每日一题Day150】LC1616分割两个字符串得到回文串 | 双指针+贪心
37 0
|
6月前
【每日一题Day225】LC2559统计范围内的元音字符串数 | 前缀和 二分查找
【每日一题Day225】LC2559统计范围内的元音字符串数 | 前缀和 二分查找
48 0
|
6月前
|
分布式计算 测试技术 索引
【数位dp】【动态规划】【KMP】1397. 找到所有好字符串
【数位dp】【动态规划】【KMP】1397. 找到所有好字符串
|
6月前
【每日一题Day204】LC1330翻转子数组得到最大的数组值 | 数学
【每日一题Day204】LC1330翻转子数组得到最大的数组值 | 数学
43 1
|
6月前
【每日一题Day368】LC421数组中两个数的最大异或值 | 字典树
【每日一题Day368】LC421数组中两个数的最大异或值 | 字典树
30 0
|
6月前
【每日一题Day129】LC1247交换字符使得字符串相同 | 贪心
【每日一题Day129】LC1247交换字符使得字符串相同 | 贪心
50 0
|
6月前
【每日一题Day122】LC1237找出给定方程的正整数解 | 双指针 二分查找
【每日一题Day122】LC1237找出给定方程的正整数解 | 双指针 二分查找
40 0
|
6月前
【每日一题Day152】LC1012至少有1位重复的数字 | 数位dp
【每日一题Day152】LC1012至少有1位重复的数字 | 数位dp
48 0
|
算法 C++
剑指offer(C++)-JZ48:最长不含重复字符的子字符串(算法-动态规划)
剑指offer(C++)-JZ48:最长不含重复字符的子字符串(算法-动态规划)