---
# System prepended metadata

title: Sliding window pattern
tags: [LeetCode]

---

---
title: 'Sliding window pattern'
author: Jay Chen
tags: 'LeetCode'
---

# Sliding windown pattern

Sliding windown technique is mostly used to solve "finding a substring" problem.

## Pattern

```python
# A: the array (string) to be scanned

Initialize the `ans` variable (maxLength)
Initialize the `count` to denote the window size
(Initialize the `required` variable in order to know if the current window is satisfied)

for r in range(len(A)):
    Modify count according to A[r]
    while the current window is already satisfied:
        Modify count according to A[l]
        Increase l
    Update the ans variable according to current sliding window
```

## Some examples

### 3. Longest Substring Without Repeating Characters

```python
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        ans = 0
        count = collections.Counter()

        l = 0
        for r, c in enumerate(s):
            count[c] += 1
            while count[c] > 1:
                count[s[l]] -= 1
                l += 1
            ans = max(ans, r - l + 1)

        return ans
```

### 76. Minimum Window Substring

```python
class Solution:
    def minWindow(self, s: str, t: str) -> str:
        count = collections.Counter(t)
        required = len(t)
        bestLeft = 0
        minLength = float('inf')

        l = 0
        for r, c in enumerate(s):
            count[c] -= 1
            if count[c] >= 0:
                required -= 1
            while required == 0:
                if r - l + 1 < minLength:
                    bestLeft = l
                    minLength = r - l + 1
                count[s[l]] += 1
                if count[s[l]] > 0:
                    required += 1
                l += 1

        return "" if minLength == float('inf') else s[bestLeft:bestLeft + minLength]
```

### 424. Longest Repeating Character Replacement

```python
class Solution:
    def characterReplacement(self, s: str, k: int) -> int:
        ans = 0
        maxFreq = 0
        count = collections.Counter()

        l = 0
        for r, c in enumerate(s):
            count[c] += 1
            maxFreq = max(maxFreq, count[c])
            while maxFreq + k < r - l + 1:
                count[s[l]] -= 1
                l += 1
            ans = max(ans, r - l + 1)

        return ans
```

### 438. Find All Anagrams ina String

> Method 1 (similar to 424. Longest Repeating Character Replacement)
> First, find the substring (sliding window) in `s`
> Second, check if the window's length equals to `p`'s length

```python
class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        ans = []
        count = collections.Counter(p)
        required = len(p)

        l = 0
        for r, c in enumerate(s):
            count[c] -= 1
            if count[c] >= 0:
                required -= 1
            while required == 0:
                if r - l + 1 == len(p):
                    ans.append(l)
                count[s[l]] += 1
                if count[s[l]] > 0:
                    required += 1
                l += 1

        return ans
```

> Method 2 (Similar to 567. Permutation in String)
> First, fix the window's length
> Second, check if `required == 0` (i.e., the window contains all characters in `s2`)

```python
class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        ans = []
        count = collections.Counter(p)
        required = len(p)

        for r, c in enumerate(s):
            count[c] -= 1
            if count[c] >= 0:
                required -= 1
            if r >= len(p):
                count[s[r - len(p)]] += 1
                if count[s[r - len(p)]] > 0:
                    required += 1
            if required == 0:
                ans.append(r - len(p) + 1)

        return ans
```

### 567. Permutation in String

```python
class Solution:
    def checkInclusion(self, s1: str, s2: str) -> bool:
        count_s1 = collections.Counter(s1)
        required = len(s1)

        for r, c in enumerate(s2):
            count_s1[c] -= 1
            if count_s1[c] >= 0:
                required -= 1
            if r >= len(s1):
                count_s1[s2[r - len(s1)]] += 1
                if count_s1[s2[r - len(s1)]] > 0:
                    required += 1
            if required == 0:
                return True

        return False
```

### 904. Fruit Into Baskets

```python
class Solution:
    def totalFruit(self, tree: List[int]) -> int:
        ans = 0
        count = collections.defaultdict(int)

        l = 0
        for r, t in enumerate(tree):
            count[t] += 1
            while len(count) > 2:
                count[tree[l]] -= 1
                if count[tree[l]] == 0:
                    del count[tree[l]]
                l += 1
            ans = max(ans, r - l + 1)

        return ans
```

### 1004. Max Consecutive Ones III

```python
class Solution:
    def longestOnes(self, A: List[int], K: int) -> int:
        ans = 0

        l = 0
        for r, a in enumerate(A):
            if a == 0:
                K -= 1
            while K < 0:
                if A[l] == 0:
                    K += 1
                l += 1
            ans = max(ans, r - l + 1)

        return ans
```

### 992. Subarrays with K Different Integers

```python
class Solution:
    def subarraysWithKDistinct(self, A: List[int], K: int) -> int:
        def subarraysWithAtMostKDistinct(K: int) -> int:
            ans = 0
            count = collections.Counter()

            l = 0
            for r, a in enumerate(A):
                count[a] += 1
                if count[a] == 1:
                    K -= 1
                while K < 0:
                    count[A[l]] -= 1
                    if count[A[l]] == 0:
                        K += 1
                    l += 1
                ans += r - l + 1

            return ans

        return subarraysWithAtMostKDistinct(K) - subarraysWithAtMostKDistinct(K - 1)
```
