Skip to main content

Using Sliding Window Pattern

1. Understanding Window Types

Type Description Use Case Example
Fixed-size window Window size is constant throughout the algorithm. Find maximum sum of k elements in array.
const maxSum = (arr, k) => {
  let windowSum = arr.slice(0, k).reduce((a, b) => a + b, 0);
  let maxSum = windowSum;
  for (let i = k; i < arr.length; i++) {
    windowSum = windowSum - arr[i - k] + arr[i];
    maxSum = Math.max(maxSum, windowSum);
  }
  return maxSum;
};
Variable-size window Window size changes dynamically based on conditions. Find the longest substring with at most k distinct characters.
const lengthOfLongestSubstringKDistinct = (s, k) => {
  let left = 0;
  let maxLength = 0;
  const charCount = new Map();
  for (let right = 0; right < s.length; right++) {
    const char = s[right];
    charCount.set(char, (charCount.get(char) || 0) + 1);
    while (charCount.size > k) {
      const leftChar = s[left];
      charCount.set(leftChar, charCount.get(leftChar) - 1);
      if (charCount.get(leftChar) === 0) {
        charCount.delete(leftChar);
      }
      left++;
    }
    maxLength = Math.max(maxLength, right - left + 1);
  }
  return maxLength;
};
Expanding and contracting window Window expands until condition is met, then contracts to find optimal solution. Find the minimum window substring that contains all characters of another string.
const minWindow = (s, t) => {
  const need = new Map();
  const window = new Map();
  for (let c of t) {
    need.set(c, (need.get(c) || 0) + 1);
  }
  let left = 0, right = 0;
  let valid = 0;
  let start = 0, len = Infinity;
  while (right < s.length) {
    const c = s[right];
    right++;
    if (need.has(c)) {
      window.set(c, (window.get(c) || 0) + 1);
      if (window.get(c) === need.get(c)) {
        valid++;
      }
    }
    while (valid === need.size) {
      if (right - left < len) {
        start = left;
        len = right - left;
      }
      const d = s[left];
      left++;
      if (need.has(d)) {
        if (window.get(d) === need.get(d)) {
          valid--;
        }
        window.set(d, window.get(d) - 1);
      }
    }
  }
  return len === Infinity ? "" : s.substring(start, start + len);
};

2. Finding Maximum Sum Subarray

Property Description Example
array Input array of integers [1, 2, 3, 4, 5]
k Size of the sliding window 3
maxSum Maximum sum of any subarray of size k 12

Example: Maximum Sum Subarray of Size k

function maxSumSubarray(arr, k) {
  let windowSum = arr.slice(0, k).reduce((a, b) => a + b, 0);
  let maxSum = windowSum;

  for (let i = k; i < arr.length; i++) {
    windowSum = windowSum - arr[i - k] + arr[i];
    maxSum = Math.max(maxSum, windowSum);
  }

  return maxSum;
}

// Example usage:
const nums = [2, 1, 5, 1, 3, 2];
const k = 3;
console.log(maxSumSubarray(nums, k)); // Output: 9
Note: The sliding window technique is efficient for finding maximum or minimum values in a fixed-size window over an array.

3. Finding Longest Substring Without Repeats

Property Description Example
Algorithm Sliding window technique to find the longest substring without repeating characters int maxLength = 0;
Time Complexity O(n) where n is the length of the string for (int i = 0; i < n; i++) { ... }
Space Complexity O(min(m,n)) where m is the size of the character set Map<Character, Integer> charIndexMap = new HashMap<>();

Example: Sliding Window Implementation

public static int lengthOfLongestSubstring(String s) {
    Map<Character, Integer> charIndexMap = new HashMap<>();
    int maxLength = 0;
    int left = 0;

    for (int right = 0; right < s.length(); right++) {
        char currentChar = s.charAt(right);
        if (charIndexMap.containsKey(currentChar)) {
            left = Math.max(left, charIndexMap.get(currentChar) + 1);
        }
        charIndexMap.put(currentChar, right);
        maxLength = Math.max(maxLength, right - left + 1);
    }

    return maxLength;
}
Note: The sliding window adjusts the left pointer whenever a repeated character is found, ensuring all characters in the current window are unique.

4. Finding Minimum Window Substring

Property Description Example
slidingWindow Finds the smallest substring in s that contains all characters of t minWindow("ADOBECODEBANC", "ABC") // returns "BANC"
left, right Pointers defining the current window in s left = 0; right = 0;
requiredChars Map of characters in t and their counts {A: 1, B: 1, C: 1}
windowChars Map of characters in current window and their counts {A: 1, D: 1}
minLength Length of the minimum valid window found so far Integer.MAX_VALUE
minStart Start index of the minimum valid window found so far -1

Example: Sliding Window to Find Minimum Substring

function minWindow(s, t) {
    const requiredChars = {};
    for (let char of t) {
        requiredChars[char] = (requiredChars[char] || 0) + 1;
    }

    let left = 0, right = 0;
    let windowChars = {};
    let minStart = -1;
    let minLength = Infinity;
    let requiredCount = Object.keys(requiredChars).length;
    let formedCount = 0;

    while (right < s.length) {
        const rightChar = s[right];
        windowChars[rightChar] = (windowChars[rightChar] || 0) + 1;

        if (requiredChars[rightChar] &&
            windowChars[rightChar] === requiredChars[rightChar]) {
            formedCount++;
        }

        while (left <= right && formedCount === requiredCount) {
            const leftChar = s[left];
            if (right - left + 1 < minLength) {
                minLength = right - left + 1;
                minStart = left;
            }

            windowChars[leftChar]--;
            if (requiredChars[leftChar] &&
                windowChars[leftChar] < requiredChars[leftChar]) {
                formedCount--;
            }
            left++;
        }
        right++;
    }

    return minStart === -1 ? "" : s.substring(minStart, minStart + minLength);
}
Note: The algorithm uses two pointers to maintain a sliding window over the string s. It expands the window by moving the right pointer and contracts it by moving the left pointer to find the minimum valid substring.

5. Finding Permutation in String

Use the sliding window pattern to check if any permutation of a pattern string exists as a substring in a given text string.

Property Description Example
pattern String to find permutations of "ab"
s Input string to search in "eidbaooo"
result Boolean indicating if any permutation exists true

Example: Check for permutation in string

function checkInclusion(pattern, s) {
  const patternCount = {};
  const windowSize = pattern.length;
  
  // Count characters in pattern
  for (let char of pattern) {
    patternCount[char] = (patternCount[char] || 0) + 1;
  }
  
  const windowCount = {};
  let left = 0;
  let matches = 0;
  
  for (let right = 0; right < s.length; right++) {
    const rightChar = s[right];
    windowCount[rightChar] = (windowCount[rightChar] || 0) + 1;
    
    // Shrink window if larger than pattern size
    if (right - left + 1 > windowSize) {
      const leftChar = s[left];
      windowCount[leftChar]--;
      if (windowCount[leftChar] === 0) {
        delete windowCount[leftChar];
      }
      left++;
    }
    
    // Check if current window matches pattern
    if (right - left + 1 === windowSize) {
      let match = true;
      for (let char in patternCount) {
        if (!(char in windowCount) || windowCount[char] !== patternCount[char]) {
          match = false;
          break;
        }
      }
      if (match) return true;
    }
  }
  
  return false;
}

// Example usage
console.log(checkInclusion("ab", "eidbaooo")); // true

6. Finding Longest Substring with K Distinct Characters

Property Description Example
Input String and integer k (number of distinct characters allowed) "araaci", k = 2
Output Length of the longest substring with at most k distinct characters 4 (substring "araa")

Example: Sliding Window Implementation

function lengthOfLongestSubstringKDistinct(s, k) {
    if (s.length === 0 || k === 0) return 0;

    let left = 0;
    let maxLength = 0;
    const charCount = new Map();

    for (let right = 0; right < s.length; right++) {
        const rightChar = s[right];
        charCount.set(rightChar, (charCount.get(rightChar) || 0) + 1);

        while (charCount.size > k) {
            const leftChar = s[left];
            charCount.set(leftChar, charCount.get(leftChar) - 1);
            if (charCount.get(leftChar) === 0) {
                charCount.delete(leftChar);
            }
            left++;
        }

        maxLength = Math.max(maxLength, right - left + 1);
    }

    return maxLength;
}

// Example usage:
console.log(lengthOfLongestSubstringKDistinct("araaci", 2)); // Output: 4
Note: The sliding window technique efficiently maintains a window of characters with at most k distinct characters by expanding the right pointer and shrinking the left pointer when the constraint is violated.

7. Solving Fruits into Baskets Problem

Example: Fruits into Baskets

function fruitsIntoBaskets(fruits) {
  let maxLength = 0;
  let windowStart = 0;
  let fruitFrequency = new Map();

  for (let windowEnd = 0; windowEnd < fruits.length; windowEnd++) {
    const rightFruit = fruits[windowEnd];
    fruitFrequency.set(rightFruit, (fruitFrequency.get(rightFruit) || 0) + 1);

    while (fruitFrequency.size > 2) {
      const leftFruit = fruits[windowStart];
      fruitFrequency.set(leftFruit, fruitFrequency.get(leftFruit) - 1);
      if (fruitFrequency.get(leftFruit) === 0) {
        fruitFrequency.delete(leftFruit);
      }
      windowStart++;
    }

    maxLength = Math.max(maxLength, windowEnd - windowStart + 1);
  }

  return maxLength;
}

// Example usage:
const fruits = ['A', 'B', 'C', 'A', 'C'];
console.log(fruitsIntoBaskets(fruits)); // Output: 3
Property Description Notes
fruits Array of fruit types Each element represents a type of fruit
maxLength Maximum number of fruits that can be collected Result of the algorithm
windowStart Start index of the sliding window Used to shrink the window when needed
fruitFrequency Map storing the count of each fruit type in the current window Used to maintain at most 2 types of fruits
Note: The algorithm uses a sliding window approach to find the longest contiguous subarray with at most 2 unique fruit types.

8. Finding Longest Repeating Character Replacement

Property Description Value
algorithm Sliding window technique Used to find the longest substring with at most k replacements
time complexity Time to process the string O(n) where n is the length of the string
space complexity Space used by the algorithm O(1) assuming fixed character set (e.g., 26 lowercase letters)

Example: Sliding Window for Replacing Characters

function characterReplacement(s, k) {
    let maxCount = 0;
    let maxLength = 0;
    let left = 0;
    const charCount = {};

    for (let right = 0; right < s.length; right++) {
        const rightChar = s[right];
        charCount[rightChar] = (charCount[rightChar] || 0) + 1;
        maxCount = Math.max(maxCount, charCount[rightChar]);

        while (right - left + 1 - maxCount > k) {
            const leftChar = s[left];
            charCount[leftChar]--;
            left++;
        }

        maxLength = Math.max(maxLength, right - left + 1);
    }

    return maxLength;
}

// Example usage:
console.log(characterReplacement("ABAB", 2)); // Output: 4
console.log(characterReplacement("AABABBA", 1)); // Output: 4
Note: The sliding window maintains a window where the number of characters that need to be replaced is less than or equal to k. The maximum length of such a window is the answer.

9. Finding Maximum Consecutive Ones

Property Description Example
Input Array of integers (0s and 1s) [1, 1, 0, 1, 1, 1]
Output Maximum number of consecutive 1s 3

Example: Sliding Window Approach

function findMaxConsecutiveOnes(nums) {
  let maxCount = 0;
  let currentCount = 0;

  for (let i = 0; i < nums.length; i++) {
    if (nums[i] === 1) {
      currentCount++;
      maxCount = Math.max(maxCount, currentCount);
    } else {
      currentCount = 0;
    }
  }

  return maxCount;
}

// Example usage:
const nums = [1, 1, 0, 1, 1, 1];
console.log(findMaxConsecutiveOnes(nums)); // Output: 3
Note: This approach uses a single pass through the array, maintaining a running count of consecutive 1s and updating the maximum count whenever a longer sequence is found.

10. Finding Minimum Size Subarray Sum

Given an array of positive integers and a target sum, find the minimum length of a contiguous subarray whose sum is at least the target.

Property Description Example
array Input array of positive integers [2, 3, 1, 2, 4, 3]
target Target sum to achieve 7
result Minimum length of subarray with sum >= target 2

Example: Finding Minimum Size Subarray Sum

function minSubArrayLen(target, nums) {
  let left = 0;
  let sum = 0;
  let minLength = Infinity;

  for (let right = 0; right < nums.length; right++) {
    sum += nums[right];

    while (sum >= target) {
      minLength = Math.min(minLength, right - left + 1);
      sum -= nums[left];
      left++;
    }
  }

  return minLength === Infinity ? 0 : minLength;
}

// Example usage:
const nums = [2, 3, 1, 2, 4, 3];
const target = 7;
console.log(minSubArrayLen(target, nums)); // Output: 2
Note: The sliding window technique is optimal here with O(n) time complexity.

11. Finding All Anagrams in String

The Sliding Window technique can be effectively used to find all anagrams of a pattern string within a given text string. This approach leverages the concept of character frequency matching.

Step Description Action
1 Initialize window size to the length of the pattern string. Set windowSize = pattern.length
2 Create frequency map for the pattern string.
const patternMap = new Map();
for (let char of pattern) {
  patternMap.set(char, (patternMap.get(char) || 0) + 1);
}
3 Slide the window over the text string and compare character frequencies.
const result = [];
const windowMap = new Map();
let left = 0;

for (let right = 0; right < text.length; right++) {
  const rightChar = text[right];
  windowMap.set(rightChar, (windowMap.get(rightChar) || 0) + 1);

  if (right - left + 1 > windowSize) {
    const leftChar = text[left];
    windowMap.set(leftChar, windowMap.get(leftChar) - 1);
    if (windowMap.get(leftChar) === 0) {
      windowMap.delete(leftChar);
    }
    left++;
  }

  if (right - left + 1 === windowSize && 
      areMapsEqual(windowMap, patternMap)) {
    result.push(left);
  }
}
4 Return all starting indices where an anagram is found. return result;

Example: Finding Anagrams in a String

function findAnagrams(text, pattern) {
  const result = [];
  const windowSize = pattern.length;
  const patternMap = new Map();
  const windowMap = new Map();

  // Build frequency map for pattern
  for (let char of pattern) {
    patternMap.set(char, (patternMap.get(char) || 0) + 1);
  }

  // Slide window over text
  for (let right = 0; right < text.length; right++) {
    const rightChar = text[right];
    windowMap.set(rightChar, (windowMap.get(rightChar) || 0) + 1);

    if (right - left + 1 > windowSize) {
      const leftChar = text[left];
      windowMap.set(leftChar, windowMap.get(leftChar) - 1);
      if (windowMap.get(leftChar) === 0) {
        windowMap.delete(leftChar);
      }
      left++;
    }

    if (right - left + 1 === windowSize && 
        areMapsEqual(windowMap, patternMap)) {
      result.push(left);
    }
  }

  return result;
}

function areMapsEqual(map1, map2) {
  if (map1.size !== map2.size) return false;
  for (let [key, value] of map1) {
    if (map2.get(key) !== value) return false;
  }
  return true;
}

// Example usage:
const text = "cbaebabacd";
const pattern = "abc";
console.log(findAnagrams(text, pattern)); // Output: [0, 6]
Note: The time complexity is O(n * m) where n is the length of the text and m is the length of the pattern. Space complexity is O(m) for storing character frequencies.

12. Finding Substring with Concatenation

The "Finding Substring with Concatenation" problem involves identifying all starting indices in a string where a concatenation of all words from a given list appears in any order.

Property Description Example
s Input string to search for concatenated substrings "barfoothefoobarman"
words List of words to concatenate and search for ["foo", "bar"]
wordLength Length of each word in the list (assumed to be equal) 3
totalLength Total length of all words combined 6

Example: Finding Concatenated Substrings

function findSubstring(s, words) {
    if (!s || !words || words.length === 0) return [];

    const wordLength = words[0].length;
    const totalLength = wordLength * words.length;
    const wordCount = {};
    const result = [];

    // Count occurrences of each word
    for (const word of words) {
        wordCount[word] = (wordCount[word] || 0) + 1;
    }

    // Slide window over each possible starting position
    for (let i = 0; i < wordLength; i++) {
        let left = i;
        let count = 0;
        const currentCount = {};

        for (let right = i; right <= s.length - wordLength; right += wordLength) {
            const word = s.substring(right, right + wordLength);
            if (wordCount[word]) {
                currentCount[word] = (currentCount[word] || 0) + 1;
                count++;

                // Adjust window if a word appears more times than allowed
                while (currentCount[word] > wordCount[word]) {
                    const leftWord = s.substring(left, left + wordLength);
                    currentCount[leftWord]--;
                    count--;
                    left += wordLength;
                }

                // If all words matched, record the index
                if (count === words.length) {
                    result.push(left);
                }
            } else {
                // Reset window if word not in list
                currentCount = {};
                count = 0;
                left = right + wordLength;
            }
        }
    }

    return result;
}

// Example usage:
const s = "barfoothefoobarman";
const words = ["foo", "bar"];
console.log(findSubstring(s, words)); // Output: [0, 9]
Note: The algorithm uses a sliding window approach to efficiently check all possible concatenated substrings without generating every permutation explicitly.

Was this article helpful?