Here’s a rewritten version of the article focusing on the problem-solving aspects:
Mastering Sliding Window: Consecutive Ones and Anagram Indices
This installment, Day 19 of my ongoing daily coding series, delves into two classic sliding window problems: “Max Consecutive Ones III” and “Find All Anagrams in a String.” Both challenges provide excellent opportunities to solidify the fundamental principles of the sliding window technique.
Key Takeaways from Today’s Problems
- Max Consecutive Ones III: This problem highlights the adaptive nature of the sliding window. The window dynamically expands, and when the condition (more than
k
zeros) is violated, it contracts from the left. This ensures that we always maintain a valid window while searching for the maximum possible length. - Find All Anagrams in a String: For detecting anagrams within a larger string, frequency counters prove to be an efficient tool. By maintaining character counts for both the target pattern and the current window, we can identify anagrams in linear time.
- Sliding Window Template Reinforcement: Both problems underscore the core sliding window approach: progressively expand the window, conditionally shrink it to maintain validity, and update the result with each valid window.
Deep Dive: #1004 — Max Consecutive Ones III
The goal here is to find the longest subarray containing only 1s, where we’re allowed to flip up to k
zeros to ones.
Python Solution
class Solution:
def longestOnes(self, nums: List[int], k: int) -> int:
n = len(nums)
left = 0
zero_count = 0 # Tracks zeros in the current window
max_length = 0
for right in range(n):
if nums[right] == 0:
zero_count += 1
# If current zeros exceed k, shrink window from left
while zero_count > k:
if nums[left] == 0:
zero_count -= 1
left += 1
# Update max_length for the valid window
max_length = max(max_length, right - left + 1)
return max_length
C++ Solution
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
int n = nums.size();
int left = 0;
int zero_count = 0; // Tracks zeros in the current window
int max_length = 0;
for (int right = 0; right < n; ++right) {
if (nums[right] == 0) {
zero_count++;
}
// If current zeros exceed k, shrink window from left
while (zero_count > k) {
if (nums[left] == 0) {
zero_count--;
}
left++;
}
// Update max_length for the valid window
max_length = max(max_length, right - left + 1);
}
return max_length;
}
};
Complexity Analysis: Both implementations achieve O(n)
time complexity as each element is visited at most twice (by left
and right
pointers). The space complexity is O(1)
.
Deep Dive: #438 — Find All Anagrams in a String
This problem requires identifying all starting indices of substrings in s
that are anagrams of string p
.
Python Solution
from collections import Counter
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
n, m = len(s), len(p)
if m > n:
return []
p_freq = Counter(p)
window_freq = Counter(s[:m])
result_indices = []
# Check initial window
if window_freq == p_freq:
result_indices.append(0)
# Slide the window across the rest of the string
for i in range(m, n):
# Add new character to window
window_freq[s[i]] += 1
# Remove character leaving the window
left_char = s[i - m]
window_freq[left_char] -= 1
if window_freq[left_char] == 0:
del window_freq[left_char] # Remove if count becomes zero to maintain accurate comparison
# Check if current window is an anagram
if window_freq == p_freq:
result_indices.append(i - m + 1) # Start index of current window
return result_indices
C++ Solution
#include <vector>
#include <string>
#include <map> // Or array for fixed alphabet size
#include <numeric> // For std::iota if using array
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
int n = s.size();
int m = p.size();
if (m > n) return {};
// Use arrays for fixed-size alphabet (a-z) for better performance
vector<int> p_freq(26, 0);
vector<int> window_freq(26, 0);
for (char c : p) {
p_freq[c - 'a']++;
}
vector<int> result_indices;
int left = 0;
for (int right = 0; right < n; ++right) {
window_freq[s[right] - 'a']++; // Expand window
// When window size matches p's length
if (right - left + 1 == m) {
if (window_freq == p_freq) { // Compare frequencies
result_indices.push_back(left);
}
window_freq[s[left] - 'a']--; // Shrink window
left++;
}
}
return result_indices;
}
};
Complexity Analysis: Both solutions run in O(n)
time. The space complexity is O(1)
(specifically O(26)
for the alphabet frequency counters), as the size of the frequency map/array is constant regardless of input string length.
Concluding Achievements
Today’s session successfully demonstrated the versatility of the sliding window paradigm:
- Max Consecutive Ones III: Effectively implemented the expansion and conditional shrinking of the window to count zeros and maximize the length of consecutive ones.
- Find All Anagrams in a String: Utilized frequency matching (using
Counter
in Python and arrays in C++) to precisely locate all anagram starting indices.
This systematic approach reinforces core data structure and algorithm concepts, leading to efficient and robust solutions.