Sliding Window & Two Pointer¶
Sliding Window maintains a window over data and slides it to find optimal subarrays/substrings. Two types: fixed-size (window always size K) and variable-size (expand/shrink based on condition). Two Pointer uses two indices moving towards each other or in the same direction. Both avoid nested loops, reducing O(n²) to O(n).
Key Concepts¶
Deep Dive: Fixed-Size Sliding Window
Maximum sum subarray of size K:
Deep Dive: Variable-Size Sliding Window
Longest substring without repeating characters:
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> lastSeen = new HashMap<>();
int maxLen = 0, left = 0;
for (int right = 0; right < s.length(); right++) {
char c = s.charAt(right);
if (lastSeen.containsKey(c)) {
left = Math.max(left, lastSeen.get(c) + 1);
}
lastSeen.put(c, right);
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
Minimum window substring:
public String minWindow(String s, String t) {
Map<Character, Integer> need = new HashMap<>();
for (char c : t.toCharArray()) need.merge(c, 1, Integer::sum);
int left = 0, minStart = 0, minLen = Integer.MAX_VALUE, matched = 0;
for (int right = 0; right < s.length(); right++) {
char c = s.charAt(right);
if (need.containsKey(c)) {
need.merge(c, -1, Integer::sum);
if (need.get(c) >= 0) matched++;
}
while (matched == t.length()) {
if (right - left + 1 < minLen) {
minLen = right - left + 1;
minStart = left;
}
char leftChar = s.charAt(left++);
if (need.containsKey(leftChar)) {
need.merge(leftChar, 1, Integer::sum);
if (need.get(leftChar) > 0) matched--;
}
}
}
return minLen == Integer.MAX_VALUE ? "" : s.substring(minStart, minStart + minLen);
}
Deep Dive: Two Pointer Patterns
Container With Most Water:
public int maxArea(int[] height) {
int left = 0, right = height.length - 1, max = 0;
while (left < right) {
int area = Math.min(height[left], height[right]) * (right - left);
max = Math.max(max, area);
if (height[left] < height[right]) left++;
else right--;
}
return max;
}
3Sum:
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] == nums[i-1]) continue; // Skip duplicates
int left = i + 1, right = nums.length - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum == 0) {
result.add(List.of(nums[i], nums[left], nums[right]));
while (left < right && nums[left] == nums[left+1]) left++;
while (left < right && nums[right] == nums[right-1]) right--;
left++; right--;
} else if (sum < 0) left++;
else right--;
}
}
return result;
}
Common Interview Questions
- Longest Substring Without Repeating Characters
- Minimum Window Substring
- Sliding Window Maximum
- Maximum Sum Subarray of Size K
- Container With Most Water
- 3Sum
- Trapping Rain Water
- Longest Repeating Character Replacement
- Permutation in String
- Fruit Into Baskets