1177. 构建回文串检测
题目
给你一个字符串 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,可以认为每次检测都是独立的)
示例
输入:s = "abcda", queries = [[3,3,0],[1,2,0],[0,3,1],[0,3,2],[0,4,1]]
输出:[true,false,false,true,true]
解释:
queries[0] : 子串 = "d",回文。
queries[1] : 子串 = "bc",不是回文。
queries[2] : 子串 = "abcd",只替换 1 个字符是变不成回文串的。
queries[3] : 子串 = "abcd",可以变成回文的 "abba"。 也可以变成 "baab",先重新排序变成 "bacd",然后把 "cd" 替换为 "ab"。
queries[4] : 子串 = "abcda",可以变成回文的 "abcba"。
复制代码
提示
- 中只有小写英文字母
题解
前缀和 + 状态压缩
字符串长度和检测数组长度达到 算法复杂度要低于 ;
根据提示,s中只有小写英文字母
可以将s的英文字母放在长度为26的数组中。通过枚举s得到一个字符串数量前缀数组list; list[i] = 当前字符串之前26个英文字母分别出现的次数;
在枚举检测数组时,通过检测数组queries[i] = [left, right, k]中left和right在list数组中找到left和right位置26个英文字母分别出现的次数;二者相减可得[left,right]区间26个英文字母分别出现的次数
检验区间[left,right]是否可以组成回文保存结果
返回结果数组即可
var canMakePaliQueries = function (s, queries) {
const path = Array(26).fill(0)
const list = [[...path]]
const len = s.length
for (let i = 0; i < len; i++) {
const idx = s[i].charCodeAt() - 'a'.charCodeAt()
path[idx]++
list.push([...path])
}
let result = []
for (let i = 0; i < queries.length; i++) {
const [left, right, k] = queries[i]
const l = list[left]
const r = list[right + 1]
let count = 0
for (let j = 0; j < 26; j++) {
const t = r[j] - l[j]
if (t % 2 === 1) count++
}
result[i] = k >= (count - 1) / 2
}
return result
}
复制代码
结语
作者水平有限,如有不足欢迎指正;任何意见和建议欢迎评论区浏览讨论
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END