---
# System prepended metadata

title: Sliding Window

---

# Sliding Window
## Introduction

Working with pointers reduces the complexity of O(n^2) to O(n).

Average of subarrays size K:

```python
# Brute force (O(n^2))
def average_of_subarrays_of_size_k_BF(k: int, arr: list):
    result = []
    # Iterations
    for ix, element in enumerate(range(len(arr) - k + 1)):
        result.append((sum(arr[ix: k + ix]) / k))
    
    return result


# Optimal (O(n))
def average_of_subarrays_of_size_k_OPT(k: int, arr: list):
    result = []
    # Insert first result
    current_sum = round((sum(arr[:k]) / 5), 1)
    result.append(current_sum)
    
    # Create sliding window pointers
    start_point = 0
    end_point = 5
    
    # Iterations
    for it in range(1, len(arr) - k + 1):
        current_sum = current_sum - (arr[start_point] / k) + (arr[end_point] / k)
        result.append(round(current_sum, 1))
        start_point = start_point + 1
        end_point = end_point + 1

    return result
```

Max sum of subarrays size K:

```python
# Optimal (O(n))
def max_sum_of_subarrays_of_size_k_OPT(k: int, arr: list):
    # Insert first result
    max_sum = round(sum(arr[:k]), 1)
    temp_sum = max_sum
    
    # Create sliding window pointers
    start_point = 0
    end_point = k
    
    # Iterations
    for it in range(1, len(arr) - k + 1):       
        temp_sum = temp_sum - arr[start_point] + arr[end_point]       
        max_sum = temp_sum if temp_sum > max_sum else max_sum
        
        start_point = start_point + 1
        end_point = end_point + 1

    return max_sum
```

Smallest subarray for given sum:

```python
# Suboptimal (O(n^2))
def sum_of_subarrays_of_size_k_BF(k: int, s: int, arr: list):
    # Insert first result
    max_sum = round(sum(arr[:k]), 1)
    current_slice = arr[:k]
    # return result immediately if S is found
    if (max_sum >= s): return max_sum, current_slice
    
    # Create sliding window pointers
    temp_sum = max_sum
    start_point = 0
    end_point = k
    
    # Iterations
    for it in range(1, len(arr) - k + 1):    
        current_slice = arr[start_point+ 1:end_point + 1 ]   
        temp_sum = temp_sum - arr[start_point] + arr[end_point]       
        max_sum = temp_sum if temp_sum > max_sum else max_sum
        
        start_point = start_point + 1
        end_point = end_point + 1
        current_slice = arr[start_point:end_point] 
        
        if (max_sum >= s): return max_sum, current_slice

    return max_sum, current_slice


def smallest_subarray_with_given_sum_SUB_OPT(s: int, arr: list):
    for sub_array_size in range(1, len(arr)):
        max_sum, min_slice = sum_of_subarrays_of_size_k_BF(sub_array_size, s, arr)
        if (max_sum >= s): 
            print(min_slice)
            return min_slice
    return -1

# Optimal (O(n))
def smallest_subarray_with_given_sum(s: int, arr: list):
    # Create sliding window pointers
    start_point = 0
    end_point = 0
    current_sum = sum(arr[start_point:end_point + 1])
    min_sub_len = -1

    while start_point <= len(arr) and end_point <= len(arr):
        # Determine sub array
        if current_sum >= s:
            current_sum = current_sum - arr[start_point]
            start_point = start_point + 1
        elif current_sum < s:
            end_point = end_point + 1
            if (end_point < len(arr)):
                current_sum = current_sum + arr[end_point]
        
        # Calculate min length of sub array   
        if current_sum >= s:
            curr_sub_len = end_point - start_point + 1
            min_sub_len = curr_sub_len if (min_sub_len == -1 or min_sub_len > curr_sub_len) else min_sub_len
     
    return min_sub_len
```

Longest substring with maximum K Distinct Characters:

