ปัญหา
กำหนดสตริงสองตัว S และ T ต้องการหา index เริ่มต้นทั้งหมดของ anagrams ของ S ที่ปรากฏใน T สตริงประกอบด้วยตัวพิมพ์เล็ก בלבד ความยาว S ≤ 20, T ≤ 100
ตัวอย่าง: S = "cab", T = "bcabxabc" → ผลลัพธ์ [0, 1, 5] เพราะ substring "bca", "cab", "abc" เป็น anagrams ของ "cab"
อัลกอริทึม (Sliding Window + Hash Map)
- สร้าง map
mเก็บความถี่ตัวอักษรใน S - ตัวแปร:
n= ความยาว T,left=0,right=0,counter= ความยาว S - ลูป
rightจาก 0 ถึง n-1:- ถ้า T[right] อยู่ใน map และ count > 0: ลด count, ลด counter, ถ้า counter=0 → เพิ่ม
leftลงคำตอบ - ถ้าไม่: ขยับ
leftไปข้างหน้าจนกว่าจะ valid อีกครั้ง (ปรับ count และ counter)
- ถ้า T[right] อยู่ใน map และ count > 0: ลด count, ลด counter, ถ้า counter=0 → เพิ่ม
- คืนค่าลิสต์ index เริ่มต้น
การนำไปใช้ (Python)
class Solution:
def findAnagrams(self, s: str, p: str):
from collections import Counter
m = Counter(p)
n = len(s)
left = 0
counter = len(p)
ans = []
for right in range(n):
if m.get(s[right], 0) > 0:
m[s[right]] -= 1
counter -= 1
if counter == 0:
ans.append(left)
else:
while left < right:
if m.get(s[left], 0) >= 0:
m[s[left]] += 1
counter += 1
left += 1
if m.get(s[right], 0) > 0:
right -= 1 # compensate for loop increment
break
if m.get(s[left], 0) == 0:
left = right + 1
return ans
# Test
ob = Solution()
print(ob.findAnagrams("bcabxabc", "cab")) # [0, 1, 5]
อธิบาย
ใช้ sliding window ความยาวเท่ากับ S รวมกับ hash map นับความถี่ตัวอักษร เมื่อ window มีตัวอักษรครบตาม S (counter=0) บันทึก index เริ่มต้น
ตัวอย่าง C++ ในต้นฉบับซับซ้อนกว่า Python version นี้เขียนใหม่ให้อ่านง่ายและ Pythonic