0Pricing
Coding Interview Prep · Lektion

Sliding Window für Teilstrings

Implementieren Sie ein Sliding Window variabler Größe, um den längsten Teilstring ohne wiederholte Zeichen und das kleinste Fenster mit allen Zielzeichen zu finden.

Sliding Window für Teilstrings ist eine kostenlose Coding Interview Prep-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Coding Interview Prep-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Coding Interview Prep-Kurs umfasst insgesamt 4 Lektionen.

Das Sliding-Window-Konzept

Ein Sliding Window umfasst ein Teilarray (oder einen Teilstring) zwischen einem linken und einem rechten Zeiger. Statt die Eigenschaften jedes möglichen Teilarrays von Grund auf in O(n²) neu zu berechnen, wird das Fenster nach rechts erweitert, indem ein Element hinzugefügt wird, und nach links verkleinert, indem ein Element entfernt wird. Dabei wird ein laufender Zustand pro Schritt in O(1) aktualisiert. Das Ergebnis ist ein O(n)-Algorithmus. Das Fenster heißt „Sliding Window“, weil es sich durch das Array vorwärtsbewegt, ohne rückwärts zu gehen.

# 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])

Feste und variable Fenstergröße

Es gibt zwei Varianten des Sliding Window. Bei einem Fenster fester Größe bewegen sich beide Zeiger im gleichen Tempo weiter, und das Fenster enthält immer genau k Elemente. Bei einem Fenster variabler Größe wird der rechte Zeiger gierig erweitert, während der linke Zeiger nur dann nachgezogen wird, wenn das Fenster eine Bedingung verletzt. Fenster variabler Größe lösen Probleme wie „längster Teilstring ohne sich wiederholende Zeichen“, bei denen die optimale Fenstergröße im Voraus unbekannt ist.

# 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))      # 2

Längster Teilstring ohne Wiederholungen

Dies ist das bekannteste Problem mit einem variablen Sliding Window. Verwenden Sie ein Set, um die Zeichen im aktuellen Fenster zu verfolgen. Erweitern Sie das Fenster nach rechts; sobald ein Duplikat gefunden wird, verkleinern Sie es von links, bis das Duplikat entfernt ist. Eine schnellere Variante verwendet eine Hashmap, in der der jeweils letzte Index jedes Zeichens gespeichert wird. Dadurch kann der linke Zeiger in einem Schritt hinter das Duplikat springen, statt schrittweise voranzurücken.

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')

Kleinstes Teilstring-Fenster

Gegeben sind die Strings s und t. Finden Sie das kleinste Fenster in s, das alle Zeichen von t enthält. Verwenden Sie zwei Häufigkeitsmaps: need (benötigte Zeichen) und have (Zeichen im aktuellen Fenster, die die Anforderungen erfüllen). Verfolgen Sie mit einem Zähler formed, wie viele eindeutige Zeichen aus t die Anforderungen erfüllen. Erweitern Sie das Fenster nach rechts, um Zeichen einzubeziehen. Sobald t vollständig enthalten ist, verkleinern Sie das Fenster von links, um es zu minimieren. Laufzeit: O(|s| + |t|).

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'

Sliding-Window-Vorlage

Die meisten Probleme mit einem variablen Sliding Window folgen einer Vorlage: Erweitern Sie das Fenster nach rechts, um das neue Zeichen einzubeziehen, aktualisieren Sie den Fensterzustand, prüfen Sie die Gültigkeit und verkleinern Sie das Fenster bei einer ungültigen Bedingung von links, bis es wieder gültig ist. Die entscheidende Erkenntnis ist, dass sich der linke Zeiger nur vorwärts bewegt — niemals rückwärts — und die gesamte Arbeit über alle Verkleinerungsschritte hinweg daher O(n) beträgt. Das Fenster besucht jedes Element höchstens zweimal: einmal beim Hinzufügen und einmal beim Entfernen.

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 best

Permutation in einem String

Prüfen Sie, ob eine beliebige Permutation des Musters p als Teilstring in s vorkommt. Eine Permutationsprüfung entspricht einem Fenster mit denselben Zeichenhäufigkeiten wie p. Halten Sie ein Sliding Window mit genau len(p) Zeichen aufrecht und vergleichen Sie die Häufigkeitszählungen. Der Vergleich vollständiger Counter-Objekte benötigt pro Schritt O(26) — bei englischen Kleinbuchstaben eine Konstante —, sodass insgesamt O(n × 26) = O(n) entsteht.

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'))  # False

Anagramm-Teilstrings: alle zählen

Finden Sie alle Startindizes der Anagramme von p in s. Dies ist dieselbe Technik mit einem Fenster fester Größe wie bei „Permutation in einem String“, aber statt beim ersten Treffer True zurückzugeben, sammeln wir alle passenden Positionen. Die Fenstergröße ist auf len(p) festgelegt. Wir verschieben das Fenster über s und vergleichen bei jedem Schritt die Häufigkeitszählungen.

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]

Längster Teilstring mit höchstens 2 verschiedenen Zeichen

Eine Variante des Sliding Window: Finden Sie den längsten Teilstring, der höchstens 2 verschiedene Zeichen enthält. Halten Sie eine Häufigkeitsmap der Zeichen im aktuellen Fenster aufrecht. Sobald die Map mehr als 2 Einträge enthält, bewegen Sie den linken Zeiger nach rechts, verringern die Häufigkeit und löschen den Eintrag bei null, bis die Bedingung wieder erfüllt ist. Dies ist ein Spezialfall des Problems „höchstens k verschiedene Zeichen“ mit k=2.

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')

Maximum im Sliding Window

Finden Sie das Maximum in jedem Fenster der Größe k. Eine Brute-Force-Prüfung des Maximums jedes Fensters benötigt O(n×k). Der optimale Ansatz verwendet eine monotone Deque von Indizes: Halten Sie eine absteigend sortierte Deque aufrecht, sodass das vorderste Element immer der Index des aktuellen Fensterm maximums ist. Entfernen Sie Indizes am Anfang, sobald sie das Fenster verlassen, und am Ende, sobald ein größeres Element hinzukommt. Die Gesamtlaufzeit beträgt O(n).

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]

Wann Sie Sliding Window verwenden sollten

Verwenden Sie Sliding Window, wenn Sie Folgendes sehen:

  • Teilstrings oder Teilarrays mit einer Bedingung (maximale Länge, Summe = k, höchstens k verschiedene Zeichen)
  • Eine feste Fenstergröße mit einer Aggregation (Maximum, Summe, Häufigkeit)
  • Fragen zu zusammenhängenden Bereichen (keine beliebigen Teilmengen)
Verwenden Sie Sliding Window NICHT für nicht zusammenhängende Auswahlen, Probleme, die alle Permutationen erfordern (verwenden Sie Backtracking), oder Probleme, bei denen der Zustand nicht schrittweise aktualisiert werden kann. Die entscheidende Frage lautet: Können Sie den Zustand beim Hinzufügen oder Entfernen eines Elements in O(1) aktualisieren?

# 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]))  # 2

Gültige Fenster zählen: höchstens K

Bei manchen Problemen soll die Anzahl der Teilarrays ermittelt werden, die eine Bedingung erfüllen. Ein nützlicher Trick besteht darin, Teilarrays mit höchstens k verschiedenen Zeichen zu zählen und anschließend die Anzahl mit genau k zu berechnen: exactly(k) = at_most(k) - at_most(k-1). Jeder Aufruf von at_most benötigt O(n), sodass insgesamt O(n) entsteht. Die Funktion at_most zählt Fenster, in denen die Anzahl der verschiedenen Zeichen k nicht überschreitet, indem sie right - left + 1 addiert — die Anzahl aller gültigen linken Endpunkte für jedes rechte Ende.

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))  # 9

Kurzer Test

Testen Sie Ihr Verständnis der Konzepte aus Data Structures & Algorithms — Coding Interview Prep, die in dieser Lektion behandelt wurden.

Zusammenfassung der Lektion

In dieser Lektion haben Sie gelernt: Das Sliding Window vermeidet O(n²), indem es einen laufenden Fensterzustand aufrechterhält, der beim Hinzukommen und Entfernen von Elementen in O(1) aktualisiert wird, bei Fenstern fester Größe bewegen sich beide Zeiger im gleichen Tempo weiter; Fenster variabler Größe werden nach rechts gierig erweitert und nur dann nach links verkleinert, wenn eine Bedingung verletzt wird und „kleinstes Teilstring-Fenster“ sowie „Permutation in einem String“ verwenden beide einen Fensterzustand mit Häufigkeitsmap und einen Zähler für die aktuell erfüllten erforderlichen Zeichen. Als Nächstes sehen Sie sich Anagramme und Häufigkeitsmaps für Zeichen an.

Häufig gestellte Fragen

Ist die Lektion „Sliding Window für Teilstrings“ kostenlos?

Ja — der vollständige Text von „Sliding Window für Teilstrings“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Coding Interview Prep-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Coding Interview Prep-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Sliding Window für Teilstrings“?

Implementieren Sie ein Sliding Window variabler Größe, um den längsten Teilstring ohne wiederholte Zeichen und das kleinste Fenster mit allen Zielzeichen zu finden. Du übst Coding Interview Prep mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Coding Interview Prep zu starten?

Keine Vorkenntnisse erforderlich. Coding Interview Prep auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Sliding Window für Teilstrings“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Coding Interview Prep-Lektion Code schreiben und ausführen?

Ja. Jede Coding Interview Prep-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Python-String-API für Interviews
  2. Sliding Window für Teilstrings
  3. Anagramme und Zeichenhäufigkeitskarten
  4. String-Kodierung, Umkehrung und Palindrome
← Zurück zu Coding Interview Prep