leetcode
leetcode 1101 ~ 1150
构建回文串检测

构建回文串检测

难度:

标签:

题目描述

代码结果

运行时间: 102 ms, 内存: 55.7 MB


/*
 * 题目思路:
 * 使用Java Stream对题目进行处理。对于每一个查询 [left, right, k],我们统计子串中出现的每个字母的次数。
 * 然后计算出现奇数次的字母个数,如果这个数量小于等于 k + 1,则可以通过 k 次替换使得子串变为回文。
 */

import java.util.stream.IntStream;

public class Solution {
    public List<Boolean> canMakePaliQueries(String s, int[][] queries) {
        int n = s.length();
        int[][] prefix = new int[n + 1][26];
        for (int i = 0; i < n; i++) {
            System.arraycopy(prefix[i], 0, prefix[i + 1], 0, 26);
            prefix[i + 1][s.charAt(i) - 'a']++;
        }

        return Arrays.stream(queries).map(query -> {
            int left = query[0], right = query[1], k = query[2];
            long oddCount = IntStream.range(0, 26)
                                     .filter(i -> (prefix[right + 1][i] - prefix[left][i]) % 2 != 0)
                                     .count();
            return oddCount / 2 <= k;
        }).collect(Collectors.toList());
    }
}

解释

方法:

题解使用了前缀XOR和位运算来有效地处理查询。首先,它通过记录每个字符的位向量(一个长度为26的位向量,每位表示一个字母是否出现奇数次)的前缀XOR数组cnt来处理字符串s。这样,任何子串s[l...r]的奇偶位图可以通过cnt[r+1] XOR cnt[l]快速获得。每个查询检查通过计算此XOR结果中置位的数量(即奇数字符的个数),然后判断是否可以通过至多k次替换使奇数个数的字符变为偶数个,从而形成回文串。

时间复杂度:

O(n + q)

空间复杂度:

O(n)

代码细节讲解

🦆
在算法中使用前缀XOR数组来处理字符串的奇偶性,这种方法如何保证能准确地反映子串中每个字符的出现次数?
前缀XOR数组通过对每个字符进行位运算来构建,每个字符被转换为一个长度为26的位向量,其中的每一位代表一个字母(从a到z),该位为1表示该字母出现奇数次,为0表示出现偶数次。当使用XOR操作更新前缀数组时,如果一个字符在新的位置再次出现,它的对应位会再次翻转(即从1变为0或从0变为1)。这样,通过XOR操作,前缀数组的每个元素都能正确地表示从字符串开始到当前位置所有字符的奇偶性。对于任何子串s[l...r],通过计算cnt[r+1] XOR cnt[l],我们可以得到子串中每个字符出现次数的奇偶性,因为XOR操作会消除出现偶数次的字符的影响(因为两次相同的翻转会抵消掉),只留下奇数次出现的字符的影响。
🦆
为什么在计算子串s[l...r]的奇数字符个数时,使用cnt[r+1] XOR cnt[l]得到的结果可以直接用来确定字符的奇偶性?
在前缀XOR数组中,每个元素都记录了从字符串开始到该点的所有字符的出现次数的奇偶性。当我们计算cnt[r+1] XOR cnt[l]时,实际上是将从开始到位置l的所有字符的奇偶性信息与从开始到位置r+1的所有字符的奇偶性信息进行XOR操作。这种操作的性质是,相同的奇偶性信息(对于同一个字符出现偶数次)会相互抵消,只留下那些在子串s[l...r]中奇数次出现的字符。因此,结果中的每一个置位(即值为1的位)都直接指示了在对应位置的字符在s[l...r]中出现了奇数次。
🦆
题解中提到,通过位运算来计算字符是否出现奇数次,具体是如何实现的?能否详细解释一下这个位运算的逻辑和过程?
具体的位运算过程如下:首先,将每个字符映射到一个位向量中的一个具体的位。例如,字符'a'对应的位向量是1(即00000000000000000000000001),字符'b'对应的位向量是2(即00000000000000000000000010),依此类推。每当字符x出现时,我们将其对应的位向量与前缀XOR数组的最后一个元素进行XOR操作。这个操作的作用是,如果该位原先为0(表示对应字符出现了偶数次或未出现),它会变为1(现在出现奇数次),反之亦然。因此,每次XOR操作都会更新前缀XOR数组以反映当前字符的出现次数的奇偶性变化。这样构建的前缀XOR数组,可以通过简单的XOR操作来查询任意子串中字符的奇偶次数状态。

相关问题