Alt Dizeler için Kayan Pencere
Yinelenen karakter içermeyen en uzun alt dizeyi ve hedef karakterlerin tümünü içeren en kısa pencereyi bulmak için değişken boyutlu kayan pencereyi uygulayın.
Alt Dizeler için Kayan Pencere, CoddyKit'te ücretsiz bir Coding Interview Prep dersidir. Bu, 4 dersinin 2. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Coding Interview Prep öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Coding Interview Prep kursu toplamda 4 dersten oluşur.
Kayan Pencere Kavramı
Bir kayan pencere, sol ve sağ işaretçi arasında bir alt dizi (veya alt dize) tutar. O(n²) içinde olası her alt dizinin özelliklerini baştan hesaplamak yerine pencere, her adımda çalışan durumu O(1) maliyetle koruyarak bir öğe eklemek için sağa doğru genişler ve bir öğe çıkarmak için soldan daralır. Sonuç O(n) zamanlı bir algoritmadır. Pencereye 'kayan' denmesinin nedeni, dizi içinde geriye gitmeden ilerlemesidir.
# Fixed-size window sum: O(n) after O(k) setup
def max_sum_window(nums, k):
window_sum = sum(nums[:k]) # initial window
best = window_sum
for i in range(k, len(nums)):
window_sum += nums[i] # add new right
window_sum -= nums[i - k] # remove old left
best = max(best, window_sum)
return best
print(max_sum_window([2,1,5,1,3,2], 3)) # 9 ([5,1,3])Sabit ve Değişken Pencere Boyutu
Kayan pencerenin iki türü vardır. Sabit boyutlu pencerede her iki işaretçi aynı hızda ilerler ve pencere her zaman tam olarak k öğe içerir. Değişken boyutlu pencerede sağ işaretçi açgözlü biçimde genişler, sol işaretçi ise yalnızca pencere bir kısıtı ihlal ettiğinde daralır. Değişken boyutlu pencereler, en uygun pencere boyutunun önceden bilinmediği 'tekrarlanan karakterler içermeyen en uzun alt dize' gibi problemleri çözer.
# Variable window: longest substring with at most k distinct chars
def longest_k_distinct(s, k):
from collections import defaultdict
freq = defaultdict(int)
left = 0
best = 0
for right in range(len(s)):
freq[s[right]] += 1
while len(freq) > k: # window invalid: shrink
freq[s[left]] -= 1
if freq[s[left]] == 0:
del freq[s[left]]
left += 1
best = max(best, right - left + 1)
return best
print(longest_k_distinct('eceba', 2)) # 3 ('ece')
print(longest_k_distinct('aa', 1)) # 2Tekrarlanmayan Karakterlerden Oluşan En Uzun Alt Dize
En bilinen değişken boyutlu kayan pencere problemidir. Geçerli penceredeki karakterleri izlemek için bir küme kullanın. Sağa doğru genişleyin; bir tekrar bulunduğunda, tekrar kaldırılana kadar soldan daraltın. Daha hızlı bir sürüm, her karakterin en son dizinini depolayan bir karma haritası kullanır; böylece sol işaretçi yavaşça ilerlemek yerine tek adımda tekrarın ötesine sıçrayabilir.
def length_of_longest_substring(s):
char_idx = {} # char -> last seen index
left = 0
best = 0
for right, c in enumerate(s):
if c in char_idx and char_idx[c] >= left:
left = char_idx[c] + 1 # jump past duplicate
char_idx[c] = right
best = max(best, right - left + 1)
return best
print(length_of_longest_substring('abcabcbb')) # 3 ('abc')
print(length_of_longest_substring('bbbbb')) # 1
print(length_of_longest_substring('pwwkew')) # 3 ('wke')Minimum Pencere Alt Dizesi
s ve t dizeleri verildiğinde, t'nin tüm karakterlerini içeren s içindeki en küçük pencereyi bulun. İki frekans haritası kullanın: need (gerekli karakterler) ve have (geçerli pencerede gereksinimi karşılayan karakterler). t içindeki kaç farklı karakterin karşılandığını (formed sayacı) izleyin. Karakterleri dahil etmek için sağa genişleyin; t'nin tamamı kapsandığında pencereyi küçültmek için solu daraltın. O(|s| + |t|) zaman.
from collections import Counter
def min_window(s, t):
if not t or not s: return ''
need = Counter(t)
have = {}
formed = 0
required = len(need)
left = 0
best = float('inf'), 0, 0
for right, c in enumerate(s):
have[c] = have.get(c, 0) + 1
if c in need and have[c] == need[c]:
formed += 1
while formed == required:
if right - left + 1 < best[0]:
best = right - left + 1, left, right
have[s[left]] -= 1
if s[left] in need and have[s[left]] < need[s[left]]:
formed -= 1
left += 1
return s[best[1]:best[2]+1] if best[0] != float('inf') else ''
print(min_window('ADOBECODEBANC', 'ABC')) # 'BANC'Kayan Pencere Şablonu
Değişken boyutlu kayan pencere problemlerinin çoğu aynı şablonu paylaşır: yeni karakteri dahil etmek için sağa doğru genişleyin, pencere durumunu güncelleyin, geçerliliği denetleyin ve geçersizse yeniden geçerli olana kadar soldan daraltın. Temel fikir, sol işaretçinin yalnızca ileriye doğru hareket etmesi, asla geriye gitmemesidir; bu nedenle tüm daraltma adımlarındaki toplam iş O(n) olur. Pencere her öğeyi en fazla iki kez ziyaret eder (bir kez eklenir, bir kez çıkarılır).
def sliding_window_template(s, condition_check, update_state, remove_state):
"""
Generic sliding window skeleton.
Adapt condition_check, update_state, remove_state per problem.
"""
left = 0
state = {} # or whatever state you need
best = 0
for right in range(len(s)):
update_state(state, s[right]) # expand window
while not condition_check(state): # window invalid
remove_state(state, s[left]) # shrink window
left += 1
best = max(best, right - left + 1)
return bestDizede Permütasyon
p kalıbının herhangi bir permütasyonunun s içinde alt dize olarak bulunup bulunmadığını denetleyin. Permütasyon denetimi, p ile aynı karakter frekansına sahip bir pencereye eşdeğerdir. Tam olarak len(p) karakterden oluşan kayan bir pencere tutun ve frekans sayılarını karşılaştırın. Her adımda tüm sayaç nesnelerini karşılaştırmak O(26)'dır (küçük harfli İngilizce için sabittir); böylece toplam süre O(n × 26) = O(n) olur.
from collections import Counter
def check_inclusion(p, s):
if len(p) > len(s): return False
need = Counter(p)
window = Counter(s[:len(p)])
if need == window: return True
for right in range(len(p), len(s)):
left = right - len(p)
window[s[right]] += 1
window[s[left]] -= 1
if window[s[left]] == 0:
del window[s[left]]
if window == need:
return True
return False
print(check_inclusion('ab', 'eidbaooo')) # True ('ba')
print(check_inclusion('ab', 'eidboaoo')) # FalseAnagram Alt Dizeleri: Tümünü Sayma
p'nin s içindeki tüm anagramlarının başlangıç dizinlerini bulun. Bu, dizede permütasyon problemindeki sabit pencere tekniğinin aynısıdır; ancak ilk eşleşmede doğru değerini döndürmek yerine eşleşen tüm konumları toplarız. Pencere boyutu len(p) olarak sabittir; pencereyi s boyunca kaydırır ve her adımda frekans sayılarını karşılaştırırız.
from collections import Counter
def find_anagrams(s, p):
result = []
need = Counter(p)
k = len(p)
window = Counter(s[:k])
if window == need:
result.append(0)
for right in range(k, len(s)):
window[s[right]] += 1
left_char = s[right - k]
window[left_char] -= 1
if window[left_char] == 0:
del window[left_char]
if window == need:
result.append(right - k + 1)
return result
print(find_anagrams('cbaebabacd', 'abc')) # [0, 6]En Fazla 2 Farklı Karakter İçeren En Uzun Alt Dize
Kayan pencerenin bir çeşididir: en fazla 2 farklı karakter içeren en uzun alt dizeyi bulun. Geçerli penceredeki karakterlerin frekans haritasını tutun. Harita 2 girdiyi aştığında, kısıt yeniden sağlanana kadar sol işaretçiyi sağa taşıyın (frekansı azaltın, sıfırsa silin). Bu, 'en fazla k farklı karakter' probleminin k=2 olan özel durumudur.
def longest_substring_two_distinct(s):
from collections import defaultdict
freq = defaultdict(int)
left = 0
best = 0
for right, c in enumerate(s):
freq[c] += 1
while len(freq) > 2:
freq[s[left]] -= 1
if freq[s[left]] == 0:
del freq[s[left]]
left += 1
best = max(best, right - left + 1)
return best
print(longest_substring_two_distinct('eceba')) # 3 ('ece')
print(longest_substring_two_distinct('ccaabbb')) # 5 ('aabbb')Kayan Pencere Maksimumu
Boyutu k olan her penceredeki maksimumu bulun. Her pencerenin maksimumunu kaba kuvvetle denetlemek O(n×k) sürer. En uygun yaklaşımda dizinlerden oluşan bir monotonik çift uçlu kuyruk kullanılır: kuyruğu azalan düzende tutarak önündeki öğenin her zaman geçerli pencerenin maksimumunun dizini olmasını sağlayın. Pencereden çıkan dizinleri önden, daha büyük bir öğe geldiğinde daha küçük dizinleri arkadan kaldırın. Toplam zaman O(n)'dir.
from collections import deque
def max_sliding_window(nums, k):
dq = deque() # stores indices, decreasing values
result = []
for i, n in enumerate(nums):
# Remove indices outside window
while dq and dq[0] < i - k + 1:
dq.popleft()
# Maintain decreasing order
while dq and nums[dq[-1]] < n:
dq.pop()
dq.append(i)
if i >= k - 1: # window is full
result.append(nums[dq[0]])
return result
print(max_sliding_window([1,3,-1,-3,5,3,6,7], 3))
# [3, 3, 5, 5, 6, 7]Kayan Pencere Ne Zaman Kullanılır
Şu durumlarda kayan pencereyi kullanmayı düşünün:
- Bir kısıtı olan alt dize / alt dizi (maksimum uzunluk, toplam = k, en fazla k farklı karakter)
- Bir toplulaştırmaya sahip sabit pencere boyutu (maksimum, toplam, frekans)
- Ardışık aralık soruları (rastgele seçilmiş alt kümeler değil)
# Recognising sliding window problems:
# 1. Fixed window: 'maximum average of subarray of length k'
def max_avg(nums, k):
s = sum(nums[:k])
best = s
for i in range(k, len(nums)):
s += nums[i] - nums[i-k]
best = max(best, s)
return best / k
print(max_avg([1,12,-5,-6,50,3], 4)) # 12.75
# 2. Variable window: 'smallest subarray with sum >= target'
def min_sub_len(target, nums):
left = s = 0
best = float('inf')
for right, n in enumerate(nums):
s += n
while s >= target:
best = min(best, right - left + 1)
s -= nums[left]; left += 1
return 0 if best == float('inf') else best
print(min_sub_len(7, [2,3,1,2,4,3])) # 2Geçerli Pencereleri Sayma: En Fazla K
Bazı problemler bir koşulu sağlayan alt dizilerin sayısını sorar. Kullanışlı bir yöntem, en fazla k farklı karakter içeren alt dizileri sayıp tam olarak k sayısını elde etmek için çıkarma yapmaktır: exactly(k) = at_most(k) - at_most(k-1). Her çağrı O(n) sürdüğünden toplam süre O(n) olur. Bu işlev, right - left + 1 değerlerini toplayarak farklı karakter sayısı k'yi aşmayan pencereleri sayar (her sağ uç için geçerli tüm sol uç noktaları).
from collections import defaultdict
def subarrays_at_most_k(s, k):
freq = defaultdict(int)
left = 0
count = 0
for right, c in enumerate(s):
freq[c] += 1
while len(freq) > k:
freq[s[left]] -= 1
if freq[s[left]] == 0: del freq[s[left]]
left += 1
count += right - left + 1 # all valid windows ending at right
return count
def subarrays_exactly_k(s, k):
return subarrays_at_most_k(s, k) - subarrays_at_most_k(s, k-1)
print(subarrays_exactly_k('araaci', 2)) # 9Hızlı Kontrol
Bu dersteki Veri Yapıları ve Algoritmalar — Kodlama Mülakatı Hazırlığı kavramlarını anlayıp anlamadığınızı sınayın.
Ders Özeti
Bu derste şunları öğrendiniz: kayan pencere, öğeler pencereye girip çıkarken O(1) içinde güncellenen çalışan bir pencere durumunu koruyarak O(n²) maliyetini ortadan kaldırır, sabit boyutlu pencerelerde her iki işaretçi aynı hızda ilerler; değişken boyutlu pencereler sağa doğru açgözlü biçimde genişler ve yalnızca bir kısıt ihlal edildiğinde sola doğru daralır ve minimum pencere alt dizesi ile dizede permütasyon problemleri, frekans haritası tabanlı pencere durumu ve o anda kaç gerekli karakterin karşılandığını izleyen bir sayaç kullanır. Sırada anagramları ve karakter frekans haritalarını inceleyeceğiz.
Sıkça Sorulan Sorular
“Alt Dizeler için Kayan Pencere” dersi ücretsiz mi?
Evet — “Alt Dizeler için Kayan Pencere” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Coding Interview Prep kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Coding Interview Prep kursu toplamda 4 dersten oluşur.
“Alt Dizeler için Kayan Pencere” dersinde ne öğreneceğim?
Yinelenen karakter içermeyen en uzun alt dizeyi ve hedef karakterlerin tümünü içeren en kısa pencereyi bulmak için değişken boyutlu kayan pencereyi uygulayın. Coding Interview Prep ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Coding Interview Prep öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Coding Interview Prep, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 2. dersidir.
“Alt Dizeler için Kayan Pencere” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Coding Interview Prep dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Coding Interview Prep dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Mülakatlar için Python Dize API’si
- Alt Dizeler için Kayan Pencere
- Anagramlar ve Karakter Sıklığı Haritaları
- Dize Kodlama, Ters Çevirme ve Palindromlar