İçeriğe atla
ΣDSA Patterns
Menü
Dil

Kalıp #01

Kayar Pencere

Temel

Diziler ve stringlerde en uzun, en kısa veya geçerli bitişik aralıklar.

Ne zaman kullanılır

Problem en uzun, en kısa veya geçerli bitişik alt dizi/alt string istediğinde. Sıra serbestçe yeniden düzenlenebiliyorsa kullanma.

Tanıma ipuçları

  • Bitişik alt dizi veya alt string
  • En uzun / en kısa / en fazla K / tam K
  • Sağı genişlet, değişmezi bozulunca solu daralt

Yaygın tuzaklar

  • En iyi uzunluğu güncellerken off-by-one (right - left + 1)
  • Daraltırken map/sayaç güncellemeyi unutmak
  • İndekslerin bitişik olması gerekmediğinde kayar pencere kullanmak

90 saniyelik tanıma egzersizi

Hangisi en iyi uyuyor?

  • Bitişik alt dizi veya alt string
  • En uzun / en kısa / en fazla K / tam K
  • Sağı genişlet, değişmezi bozulunca solu daralt

Interactive

Zihinsel model

Değişmezin tam adım adım anlatımı. Duraklat, noktalara tıkla veya ← → kullan. Her adımı kendi cümlelerinle anlatmayı hedefle.

Adım 1 / 9
a
b
c
a
b
b

best = 0

Start with an empty window. Invariant: all characters unique.

Nasıl düşünülür

Dizi üzerinde bir pencere [left, right] tut. right birer birer ilerlesin; pencere değişmezini bozunca left daralsın (çok fazla farklı karakter, toplam fazla, eksik zorunlu karakter…). Giderken en iyi geçerli pencereyi kaydet. Yukarıdaki animasyonun tamamı bu fikir: büyüt, düzelt, kaydet.

Şablon şekilleri

Şekil Ne zaman Daraltma kuralı
Maks pencere en uzun geçerli geçersizken daralt
Min pencere kısıtı kapsayan en kısa geçerliyken daralt
Sabit boyut boyut k her iki ucu kaydır

Karmaşıklık temeli

Genelde O(n) zaman (her indeks en fazla bir girer/çıkar) ve frekans haritası için O(Σ) alan.

Şablondan probleme

  1. Değişmezi tanımla (pencereyi ne geçerli kılar?).
  2. Maks/min için genişletme/daraltma yönünü seç.
  3. Pencere durumunu belirle (sayım haritası, toplam, distinct küme…).
  4. Cevabı yalnızca değişmez sağlandığında güncelle.

Şablon

TypeScript, Python ve C#’te aynı iskelet. Değişmezi uyarla; yapıyı koru.

Kayar Pencere · Şablon
/**
 * Sliding window (variable length), longest valid window.
 * Expand `right`, shrink `left` while the invariant breaks, then record the answer.
 *
 * Minimum covering window: shrink while still valid, update `best` only when valid
 * (often start with `best = Infinity`).
 */
function slidingWindow(s: string): number {
  const freq = new Map<string, number>();
  let left = 0;
  let best = 0;

  const windowOk = () => {
    // Replace with the problem invariant (e.g. all unique, sum ≤ k).
    return true;
  };

  for (let right = 0; right < s.length; right++) {
    // 1) expand: add s[right] into window state
    const add = s[right]!;
    freq.set(add, (freq.get(add) ?? 0) + 1);

    // 2) shrink while the invariant is broken
    while (left <= right && !windowOk()) {
      const rem = s[left]!;
      const next = (freq.get(rem) ?? 0) - 1;
      if (next <= 0) freq.delete(rem);
      else freq.set(rem, next);
      left++;
    }

    // 3) window [left, right] is valid, update answer
    best = Math.max(best, right - left + 1);
  }

  return best;
}

export { slidingWindow };
/**
 * Sliding window (variable length), longest valid window.
 * Expand `right`, shrink `left` while the invariant breaks, then record the answer.
 *
 * Minimum covering window: shrink while still valid, update `best` only when valid
 * (often start with `best = Infinity`).
 */
function slidingWindow(s: string): number {
  const freq = new Map<string, number>();
  let left = 0;
  let best = 0;

  const windowOk = () => {
    // Replace with the problem invariant (e.g. all unique, sum ≤ k).
    return true;
  };

  for (let right = 0; right < s.length; right++) {
    // 1) expand: add s[right] into window state
    const add = s[right]!;
    freq.set(add, (freq.get(add) ?? 0) + 1);

    // 2) shrink while the invariant is broken
    while (left <= right && !windowOk()) {
      const rem = s[left]!;
      const next = (freq.get(rem) ?? 0) - 1;
      if (next <= 0) freq.delete(rem);
      else freq.set(rem, next);
      left++;
    }

    // 3) window [left, right] is valid, update answer
    best = Math.max(best, right - left + 1);
  }

  return best;
}

export { slidingWindow };