給出一個字符串 "abc",判斷它是否是字符串 "adcba" 的異位詞。
這題比較直觀的解法是使用雙指針來解答,先使用 map 記錄 s1 每個字符的個數,然後遍歷 s2,每次遍歷開啟雙指針,start 為當前遍歷索引,end 為 start + s1.length。這段區間的字符長度和 s1 一致,我們只需更新 map 列表,雙指針執行結束時,如果 map 全是 0,那麼是 s2 的子字符串是 s1 的異位詞。
下面解法和上面解法有著異曲同工之妙。
// map 全為 0
function everyZero(map){
return Object.values(map).every(i => i===0)
}
function solve(s1, s2) {
if(typeof s1 !== 'string' || typeof s2 !== 'string') return false
if(s1.length > s2.length) return false
const map = {};
// 迭代 s1,以字符為 key 存在字符個數
s1.split('').map((i, index)=>{
if(!map[i]) map[i] = 0
map[i]++
// 遇到 s2 的字符,則減
if(!map[s2[index]]) map[s2[index]] = 0
map[s2[index]]--
})
// 判斷是否開頭存在變位
const bool = everyZero(map)
if(bool) return bool
let len = s1.length;
// 迭代 s2, 新的字符則 -, 舊的字符則加
// 因為之前減了,所以後面加上,如果存在異位,則 map 全為 0
for(let i = len; i < s2.length; i++){
let val = s2[i];
if(!map[val]) map[val] = 0
map[val]--
map[s2[i - len]]++
const bool = everyZero(map)
if(bool) return bool
}
return false
}