Sliding Window Template
Sliding Window Cheatsheet Template :
Template 1: Sliding Window (Shrinkable)
Key Idea
Start with an initial window [i, j] and expand it by incrementing j.
Whenever the window becomes invalid, shrink it by incrementing i until it is valid again.
Keep track of the maximum size of the valid window.
Why Use This Template?
This template is useful when you want to maximize the size of a valid window, and the window can shrink and grow dynamically depending on the condition.
import java.util.Arrays;
class Solution {
public int maxFrequency(int[] nums, int k) {
Arrays.sort(nums); // Sort the array
long sum = 0; // Track the sum of elements in the window
int i = 0, ans = 1; // Initialize pointers and result
for (int j = 0; j < nums.length; j++) {
sum += nums[j]; // Add the current number to the sum
// Shrink the window if invalid
while ((j - i + 1L) * nums[j] - sum > k) {
sum -= nums[i]; // Remove the leftmost element
i++; // Shrink the window from the left
}
// Update the maximum valid window size
ans = Math.max(ans, j - i + 1);
}
return ans;
}
}
Essentially, we want to keep the window valid at the end of each outer for loop.
Template 2: Sliding Window (Non-shrinkable)
Key Idea
Expand the window by incrementing j.
If the window becomes invalid, shift it forward by incrementing both i and j simultaneously.
Keep track of the largest valid window encountered.
Why Use This Template?
This template works well for problems where the window can only grow when valid and must shift entirely when invalid.
import java.util.Arrays;
class Solution {
public int maxFrequency(int[] nums, int k) {
Arrays.sort(nums); // Sort the array
long sum = 0; // Track the sum of elements in the window
int i = 0, j = 0; // Initialize pointers
for (int j = 0; j < nums.length; j++) {
sum += nums[j]; // Add the current number to the sum
// Shift the window if invalid
if ((j - i + 1L) * nums[j] - sum > k) {
sum -= nums[i]; // Remove the leftmost element
i++; // Shift the window forward
}
}
return j - i; // Return the size of the largest valid window
}
}
For String Question Sliding window
class Solution {
public int solveStringProblem(String s, int k) {
// Step 1: Initialize necessary variables
int[] freq = new int[26]; // Array to store the frequency of characters (if needed)
int i = 0; // Left pointer of the sliding window
int result = 0; // Variable to store the final result (e.g., max length, count, etc.)
// Step 2: Iterate through the string with the right pointer
for (int j = 0; j < s.length(); j++) {
// Add the current character to the window
freq[s.charAt(j) - 'A']++;
// Step 3: Check if the current window is valid
while (/* Condition to check if the window is invalid */) {
// Shrink the window from the left
freq[s.charAt(i) - 'A']--;
i++;
}
// Step 4: Update the result based on the valid window
result = Math.max(result, j - i + 1); // Example: maximum window size
}
// Step 5: Return the result
return result;
}
}
When Two Substring is given
class Solution {
public int equalSubstring(String s, String t, int maxCost) {
// Step 1: Initialize necessary variables
int currentCost = 0; // Current total cost of the window
int i = 0; // Left pointer of the sliding window
int maxLength = 0; // Variable to store the maximum length of the valid substring
// Step 2: Iterate through the string with the right pointer
for (int j = 0; j < s.length(); j++) {
// Add the cost of transforming s[j] to t[j] to the current cost
currentCost += Math.abs(s.charAt(j) - t.charAt(j));
// Step 3: Shrink the window if the current cost exceeds maxCost
while (currentCost > maxCost) {
currentCost -= Math.abs(s.charAt(i) - t.charAt(i)); // Remove the cost of s[i] to t[i]
i++; // Shrink the window by moving the left pointer
}
// Step 4: Update the result based on the valid window
maxLength = Math.max(maxLength, j - i + 1);
}
// Step 5: Return the result
return maxLength;
}
}
Bit Wise Sliding Window
class Solution {
public int longestNiceSubarray(int[] nums) {
int currentOR = 0; // Tracks the bitwise OR of the current window
int i = 0; // Left pointer of the sliding window
int maxLength = 0; // Maximum length of a valid subarray
for (int j = 0; j < nums.length; j++) {
// While the new element violates the condition, shrink the window
while ((currentOR & nums[j]) != 0) {
currentOR ^= nums[i]; // Remove the leftmost element from currentOR
i++; // Move the left pointer
}
// Add the current element to currentOR
currentOR |= nums[j];
// Update the maximum length
maxLength = Math.max(maxLength, j - i + 1);
}
return maxLength;
}
}
Key Signs of Where Modifications Are Done:
Initialization:
- Define variables to track the window property (e.g., currentCost, freq[]).
Expanding the Window:
- Modify the tracked property for the element at j.
Shrinking the Window:
- Modify the tracked property for the element at i and move i forward.
Result Update:
- Optimize based on the valid window (e.g., Math.max, Math.min, or sum).
Key Differences Between Sorting and Count-Based Approaches
Aspect | Sorting | Counting/Frequency |
Use Case | Relative order or value differences matter. | Frequency or bounded distinct elements matter. |
Complexity | O(nlogn)O(n \log n)O(nlogn) due to sorting. | O(n)O(n)O(n) (or O(n+k)O(n + k)O(n+k) with frequency array). |
Window Conditions | Depends on sorted order of elements. | Depends on frequency or counts of elements. |
Examples | Maximize sum with gaps, subsequence lengths. | Substring properties, binary array problems. |