แมวและนากจัดเรียงตัวอักษรการ์ดบนโต๊ะมิ้นต์ มีหน้าต่างเลื่อนครอบกลุ่มการ์ด

LeetCode #438 Find All Anagrams: หน้าต่างเลื่อนชนะการ sort ทุกช่อง

น้องกายEngineering

โจทย์ Find All Anagrams in a String #438 ให้สตริง s กับแบบ p แล้วขอทุกดัชนีเริ่มต้นของช่วงใน s ที่เป็น anagram ของ p

แมวขี้เกียจ sort ทุกหน้าต่าง เทียบกับ p ที่ sort แล้ว — เข้าใจง่าย แต่ช้า
นากนับ ใช้ Counter / อาร์เรย์ความถี่เลื่อนหน้าต่าง — O(n)

Benchmark (เครื่องนี้)

สตริงยาวจาก 'cbaebabacd'*800, แบบ abc

วิธีเวลา
หน้าต่างเลื่อนทั้งสตริง1.99 ms
sort ทุกช่องบน s[:5000]1.24 ms (ช่วงสั้นกว่า; ทั้งสตริงจะช้ากว่ามาก)

โค้ด

from collections import Counter

def find_anagrams(s: str, p: str):
    need = Counter(p)
    window = Counter()
    missing = len(p)
    left = 0
    ans = []
    for right, ch in enumerate(s):
        window[ch] += 1
        if window[ch] <= need[ch]:
            missing -= 1
        if right - left + 1 > len(p):
            leftch = s[left]
            if window[leftch] <= need[leftch]:
                missing += 1
            window[leftch] -= 1
            left += 1
        if missing == 0:
            ans.append(left)
    return ans

assert find_anagrams("cbaebabacd", "abc") == [0, 6]
print("ok")

บารอนสรุป

สัมภาษณ์ให้อธิบายความถี่เลื่อนหน้าต่าง production ใช้แบบนับ ไม่ sort ซ้ำ

Recap

  • หาทุกจุดเริ่ม anagram ของ p ใน s
  • sort ทุกช่อง vs หน้าต่างเลื่อน O(n)
  • Benchmark: เลื่อนหน้าต่าง ~2 ms บนสตริงยาวชุดทดสอบ