问:
- 求字符串的最大回文子串
- 剑指 Offer 59 - I. 滑动窗口的最大值
解:
- Manacher
function Manacher(str) {
// 用#扩充处理字符串,使得它可以统计偶数回文子串
str = handleStr(str)
// 所有回文子串的最右边界
let rightBorder = -1
// 最右边界的子串的中点
let center = -1
// 所有字符的回文半径
const everyLength = []
let max = -1
for (let i = 0; i < str.length; i++) {
// 当前位置的最小可跳过判断的回文半径
everyLength[i] = i < rightBorder ? Math.min(everyLength[2 * center - i], rightBorder - i) : 1
// 当前位置为中心,回文半径不越界
while (i + everyLength[i] < str.length && i - everyLength[i] > -1) {
if (str[everyLength[i] + i] === str[i- everyLength[i]]) {
everyLength[i]++
} else {
break
}
}
// 取所有回文子串的最右边界
if (i + everyLength[i] > rightBorder) {
rightBorder = everyLength[i] + i
center = i
}
// 回文半径最大值
max = Math.max(everyLength[i], max)
}
// 字符被扩充过,所以回文半径-1就是真实字符串的回文直径
return max - 1
function handleStr(str) {
const strArr = str.split('')
strArr.push('')
strArr.unshift('')
return strArr.join('#')
}
}
- 创建一个队列,遍历数组,若当前值不大于队列的最后一位就放进去,否则弹出队列的最后一位,直到遇到符合条件的值或者直到弹空为止。当遍历次数小于size时先不计算窗口最大值,因为这个窗口还不完整。当窗口完整创建后,队列的第一位就是最大值。放入结果数组,若窗口最左值是最大值,那么就移除队列中这个值,因为窗口右移就不再包含这个值。
function slidingWindow(arr, size) {
const res = []
const queue = []
let left = 0
let right = 0
while (right < arr.length) {
while (queue.length && queue[queue.length - 1] < arr[right]) {
queue.pop()
}
queue[queue.length] = arr[right]
right++
if (right < size) continue
res[res.length] = queue[0]
if (arr[left] === queue[0]) {
queue.shift()
}
left++
}
return res
}