# 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: