Find Smallest window that contains all characters of string itself
HardUpdated: Sep 19, 2025
Problem
Given a string s, find the shortest substring (window) that contains every distinct character that appears in s at least once. Return the substring (or its length).
Examples
Example 1
Input: s = "aabcbcdbca"
Output: "dbca" // length 4
Example 2
Input: s = "aaab"
Output: "ab" // length 2
Solution
We can solve this with a sliding-window (two-pointer) technique and a frequency table that tracks how many distinct characters inside the current window have non-zero counts.
Method 1 — Sliding window counting distinct characters
Intuition
If the string has k distinct characters overall, any valid window must contain at least one occurrence of each of those k characters. Expand the right end to include characters until the window contains all k distinct characters, then shrink from the left to remove redundant characters and record the smallest valid window seen.
Approach
- Precompute
k= number of distinct characters ins(by scanning once). - Use an array or map
freqto track character counts inside the current window, two pointersl = 0,r = 0, andcount = 0which counts how many distinct characters in the window currently have count >= 1. - Expand
rfrom 0..n-1:- Increment
freq[s[r]]; if its new count is 1, incrementcount. - While
count == k, try to shrink the window from the left:- Update best window if current length
r-l+1is smaller. - Decrement
freq[s[l]]; iffreq[s[l]]becomes 0, decrementcount. - Increment
l.
- Update best window if current length
- Increment
- At the end
bestholds the smallest window (or its length).
Edge cases:
- Empty string -> return empty substring / length 0.
- All characters the same -> shortest window is of length 1.
Code
C++
#include <string>
#include <vector>
#include <limits>
class Solution {
public:
std::string smallestWindow(const std::string &s) {
if (s.empty()) return "";
const int ALPHA = 256;
std::vector<int> seen(ALPHA, 0);
int distinct = 0;
for (unsigned char c : s) if (seen[c]++ == 0) ++distinct;
std::vector<int> freq(ALPHA, 0);
int count = 0; // distinct characters in window
int l = 0;
int bestLen = std::numeric_limits<int>::max();
int bestStart = 0;
for (int r = 0; r < (int)s.size(); ++r) {
unsigned char c = s[r];
if (freq[c]++ == 0) ++count;
while (count == distinct) {
if (r - l + 1 < bestLen) {
bestLen = r - l + 1;
bestStart = l;
}
unsigned char lc = s[l];
if (--freq[lc] == 0) --count;
++l;
}
}
return bestLen == std::numeric_limits<int>::max() ? std::string() : s.substr(bestStart, bestLen);
}
};
Go
package main
import "math"
func smallestWindow(s string) string {
if len(s) == 0 { return "" }
const ALPHA = 256
var seen [ALPHA]int
distinct := 0
for i := 0; i < len(s); i++ {
b := s[i]
if seen[b] == 0 { distinct++ }
seen[b]++
}
var freq [ALPHA]int
count := 0
l := 0
bestLen := math.MaxInt32
bestStart := 0
for r := 0; r < len(s); r++ {
b := s[r]
if freq[b] == 0 { count++ }
freq[b]++
for count == distinct {
if r-l+1 < bestLen {
bestLen = r-l+1
bestStart = l
}
lb := s[l]
freq[lb]--
if freq[lb] == 0 { count-- }
l++
}
}
if bestLen == math.MaxInt32 { return "" }
return s[bestStart:bestStart+bestLen]
}
Java
class Solution {
public String smallestWindow(String s) {
if (s == null || s.isEmpty()) return "";
final int ALPHA = 256;
int[] seen = new int[ALPHA];
int distinct = 0;
for (int i = 0; i < s.length(); ++i) if (seen[s.charAt(i)]++ == 0) ++distinct;
int[] freq = new int[ALPHA];
int count = 0, l = 0;
int bestLen = Integer.MAX_VALUE, bestStart = 0;
for (int r = 0; r < s.length(); ++r) {
if (freq[s.charAt(r)]++ == 0) ++count;
while (count == distinct) {
if (r - l + 1 < bestLen) { bestLen = r - l + 1; bestStart = l; }
if (--freq[s.charAt(l)] == 0) --count;
++l;
}
}
return bestLen == Integer.MAX_VALUE ? "" : s.substring(bestStart, bestStart + bestLen);
}
}
Python
class Solution:
def smallestWindow(self, s: str) -> str:
if not s:
return ""
ALPHA = 256
seen = [0] * ALPHA
distinct = 0
for ch in s:
b = ord(ch)
if seen[b] == 0:
distinct += 1
seen[b] += 1
freq = [0] * ALPHA
count = 0
l = 0
best_len = float('inf')
best_start = 0
for r, ch in enumerate(s):
b = ord(ch)
if freq[b] == 0:
count += 1
freq[b] += 1
while count == distinct:
if r - l + 1 < best_len:
best_len = r - l + 1
best_start = l
lb = ord(s[l])
freq[lb] -= 1
if freq[lb] == 0:
count -= 1
l += 1
return "" if best_len == float('inf') else s[best_start:best_start+best_len]
Complexity
- ⏰ Time complexity:
O(n)— each character is visited at most a constant number of times while expanding and contracting the window. - 🧺 Space complexity:
O(k)wherekis the alphabet size (herek = 256for ASCII); if using dynamic maps the space isO(min(n, alphabet)).