原題鏈接:
https://leetcode.cn/problems/replace-the-substring-for-balanced-string/
解題要點:
- 我們從字符串中截取一部分
m
雅任,只要剩下的部分每個字符的數(shù)量都小于n / 4
,就表示s
能夠通過替換m
個字符咨跌,變?yōu)椤捌胶庾址?/li> - 使用兩個指針
left
和right
沪么,將兩者之間長度為right - left + 1
的字符串當(dāng)做一個窗口,即可在s
中截取出長度為m
的字符串 - 窗口的右邊界
right
從0
開始一直移動到n - 1
位置锌半,左邊界left
跟隨right
移動禽车,查找合適的窗口 - 當(dāng)窗口移動到最右側(cè)時,例如
s = "QQWQQEQR"
,窗口到最右側(cè)時殉摔,left = 4; right = 7
州胳,此時在窗口中的字符串為QEQR
,窗口即使繼續(xù)向右移動逸月,也無法滿足上述條件陋葡,直接退出循環(huán)即可
解題思路:
- 先用
map
統(tǒng)計字符串s
中各個字符的數(shù)量 - 如果
QWER
中每個字符的數(shù)量都是n / 4
,表示s
就是“平衡字符串” - 創(chuàng)建
left
和right
指針彻采,right
從左向右移動腐缤,同時left <= right
- 每次
right
向右移動一位,就將map[s[right]]
的數(shù)量減一肛响,表示有字符移入窗口 - 每次
left
向左移動一位岭粤,就將map[s[left++]]
加一,表示有字符移出窗口 - 每次移入移出操作后特笋,
map
中剩下的字符剃浇,就是窗口外的字符數(shù)量,因此只要判斷QWER
的數(shù)量是否小等于n / 4
即可
/**
* @param {string} s
* @return {number}
*/
var balancedString = function(s) {
// 實用map統(tǒng)計當(dāng)前字符串s中各個字符的數(shù)量
let map = {
'Q': 0,
'W': 0,
'E': 0,
'R': 0,
}
// 統(tǒng)計各個字符的數(shù)量
for (const c of s) {
map[c]++
}
const n = s.length
// 計算如果是平衡字符串猎物,每個字符的數(shù)量
const target = n / 4
// 如果每個字符的數(shù)量都為n / 4虎囚,s為平衡字符串
if (
map.Q === target &&
map.W === target &&
map.E === target &&
map.R === target
) {
return 0
}
// 緩存結(jié)果,最大值為n - 1蔫磨,初始值大于等于n - 1即可
let result = n - 1
// 實用兩個指針淘讥,從字符串中截取一個范圍
for (let left = 0, right = 0; right < n; right++) {
// 每次滑入窗口一個字符,就將其數(shù)量減一
map[s[right]]--
// 字符串中除了窗口以外的部分堤如,每個字符的數(shù)量都小等于target
// 就意味著字符串能夠通過變換right - left + 1個字符蒲列,成為“平衡字符串”
while (
// 左指針必須小等于右指針,才能形成窗口
left <= right &&
// 查看窗口以外的字符搀罢,數(shù)量是否都小于target
map.Q <= target &&
map.W <= target &&
map.E <= target &&
map.R <= target
) {
// 在所有結(jié)果中取最小值
result = Math.min(result, right - left + 1)
// 每次查找完之后蝗岖,窗口要向右移動
// 同時會有一個字符被移出窗口,需要將它的數(shù)量加一
map[s[left++]]++
}
}
return result
};