Given two strings s and p, find the smallest substring in s consisting of all the characters (including duplicates) of the string p.
- Return an empty string in case no such substring is present.Â
- If there are multiple such substrings of the same length found, return the one with the least starting index.
Examples:Â
Input: s = "timetopractice", p = "toc"
Output: "toprac"
Explanation: "toprac" is the smallest substring in which "toc" can be found.Input: s = "zoomlazapzo", p = "oza"
Output: "apzo"
Explanation: "apzo" is the smallest substring in which "oza" can be found.Input: s = "zoom", p = "zooe"
Output: ""
Explanation: No substring is present containing all characters of p.
Table of Content
[Naive Approach] Generating All Substrings - O(n ^ 2 * 26) Time and O(26) Space
The idea is to generate all substrings of s and check which substrings contain all characters of p.
Working of Approach:
- Store the frequency of every character in p.
- Select each index of s as the starting point.
- Extend the substring and update its character frequencies.
- Check whether all required characters are present in sufficient quantities.
- Update the answer whenever a shorter valid substring is found.
#include <iostream>
#include <vector>
#include <string>
#include <climits>
using namespace std;
string minWindow(string &s, string &p)
{
int n = s.size();
// Store the frequency of each character in p
vector<int> need(26, 0);
for (char c : p)
need[c - 'a']++;
int minLen = INT_MAX;
int start = -1;
// Generate all substrings
for (int i = 0; i < n; i++)
{
vector<int> freq(26, 0);
for (int j = i; j < n; j++)
{
// Include the current character
freq[s[j] - 'a']++;
// Check whether all required characters are present
bool valid = true;
for (int k = 0; k < 26; k++)
{
if (freq[k] < need[k])
{
valid = false;
break;
}
}
// Update the smallest valid window
if (valid && j - i + 1 < minLen)
{
minLen = j - i + 1;
start = i;
}
}
}
// Return an empty string if no valid window exists
if (start == -1)
return "";
return s.substr(start, minLen);
}
int main()
{
string s = "zoomlazapzo", p = "oza";
cout << "\"" << minWindow(s, p) << "\"" << endl;
return 0;
}
#include <limits.h>
#include <stdio.h>
#include <string.h>
char *minWindow(char *s, char *p)
{
int n = strlen(s);
// Store the frequency of each character in p
int need[26] = {0};
for (int i = 0; p[i] != '\0'; i++)
need[p[i] - 'a']++;
int minLen = INT_MAX;
int start = -1;
// Generate all substrings
for (int i = 0; i < n; i++)
{
int freq[26] = {0};
for (int j = i; j < n; j++)
{
// Include the current character
freq[s[j] - 'a']++;
// Check whether all required characters are present
int valid = 1;
for (int k = 0; k < 26; k++)
{
if (freq[k] < need[k])
{
valid = 0;
break;
}
}
// Update the smallest valid window
if (valid && j - i + 1 < minLen)
{
minLen = j - i + 1;
start = i;
}
}
}
// Return an empty string if no valid window exists
if (start == -1)
return "";
// Create and return the smallest substring
static char result[100000];
strncpy(result, s + start, minLen);
result[minLen] = '\0';
return result;
}
int main()
{
char s[] = "zoomlazapzo";
char p[] = "oza";
printf("\"%s\"\n", minWindow(s, p));
return 0;
}
import java.util.Arrays;
public class GFG {
public static String minWindow(String s, String p)
{
int n = s.length();
// Store the frequency of each character in p
int[] need = new int[26];
for (char c : p.toCharArray())
need[c - 'a']++;
int minLen = Integer.MAX_VALUE;
int start = -1;
// Generate all substrings
for (int i = 0; i < n; i++) {
int[] freq = new int[26];
for (int j = i; j < n; j++) {
// Include the current character
freq[s.charAt(j) - 'a']++;
// Check whether all required characters are
// present
boolean valid = true;
for (int k = 0; k < 26; k++) {
if (freq[k] < need[k]) {
valid = false;
break;
}
}
// Update the smallest valid window
if (valid && j - i + 1 < minLen) {
minLen = j - i + 1;
start = i;
}
}
}
// Return an empty string if no valid window exists
if (start == -1)
return "";
return s.substring(start, start + minLen);
}
public static void main(String[] args)
{
String s = "zoomlazapzo";
String p = "oza";
System.out.println("\"" + minWindow(s, p) + "\"");
}
}
def minWindow(s, p):
n = len(s)
# Store the frequency of each character in p
need = [0] * 26
for c in p:
need[ord(c) - ord('a')] += 1
minLen = float('inf')
start = -1
# Generate all substrings
for i in range(n):
freq = [0] * 26
for j in range(i, n):
# Include the current character
freq[ord(s[j]) - ord('a')] += 1
# Check whether all required characters are present
valid = True
for k in range(26):
if freq[k] < need[k]:
valid = False
break
# Update the smallest valid window
if valid and j - i + 1 < minLen:
minLen = j - i + 1
start = i
# Return an empty string if no valid window exists
if start == -1:
return ""
return s[start:start + minLen]
if __name__ == '__main__':
s = "zoomlazapzo"
p = "oza"
print("\"" + minWindow(s, p) + "\"")
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG {
public static string minWindow(string s, string p)
{
int n = s.Length;
// Store the frequency of each character in p
int[] need = new int[26];
foreach(char c in p) need[c - 'a']++;
int minLen = int.MaxValue;
int start = -1;
// Generate all substrings
for (int i = 0; i < n; i++) {
int[] freq = new int[26];
for (int j = i; j < n; j++) {
// Include the current character
freq[s[j] - 'a']++;
// Check whether all required characters are
// present
bool valid = true;
for (int k = 0; k < 26; k++) {
if (freq[k] < need[k]) {
valid = false;
break;
}
}
// Update the smallest valid window
if (valid && j - i + 1 < minLen) {
minLen = j - i + 1;
start = i;
}
}
}
// Return an empty string if no valid window exists
if (start == -1)
return "";
return s.Substring(start, minLen);
}
public static void Main()
{
string s = "zoomlazapzo";
string p = "oza";
Console.WriteLine("\"" + minWindow(s, p) + "\"");
}
}
function minWindow(s, p)
{
const n = s.length;
// Store the frequency of each character in p
const need = new Array(26).fill(0);
for (const c of p) {
need[c.charCodeAt(0) - "a".charCodeAt(0)]++;
}
let minLen = Infinity;
let start = -1;
// Generate all substrings
for (let i = 0; i < n; i++) {
const freq = new Array(26).fill(0);
for (let j = i; j < n; j++) {
// Include the current character
freq[s.charCodeAt(j) - "a".charCodeAt(0)]++;
// Check whether all required characters are
// present
let valid = true;
for (let k = 0; k < 26; k++) {
if (freq[k] < need[k]) {
valid = false;
break;
}
}
// Update the smallest valid window
if (valid && j - i + 1 < minLen) {
minLen = j - i + 1;
start = i;
}
}
}
// Return an empty string if no valid window exists
if (start === -1)
return "";
return s.substring(start, start + minLen);
}
// Driver Code
const s = "zoomlazapzo";
const p = "oza";
console.log(`\"${minWindow(s, p)}\"`);
Output
"apzo"
[Better Approach] Binary Search on Answer - O(n log n) Time and O(1) Space
The idea is to use binary search on the window length from p.size() to n or s.size().
For a window size, we can check in linear time whether the window contains all characters by storing frequencies and comparing frequencies.
Working of Approach:
- Store the frequency of each character in p.
- Initialize low = p.size() and high = s.size().
- Calculate mid and check whether any substring of length mid contains all required characters.
- If a valid window exists, store its earliest starting index and search for a smaller length; otherwise, search for a larger length.
- Return the smallest valid substring found, or an empty string if no valid window exists.
#include <iostream>
#include <vector>
#include <string>
#include <climits>
using namespace std;
string minWindow(string &s, string &p)
{
int n = s.size(), m = p.size();
// If s is shorter than p, no valid window is possible
if (n < m)
return "";
// Store the frequency of characters in p
vector<int> need(26, 0);
for (char c : p)
need[c - 'a']++;
int low = m, high = n;
int start = -1, minLen = INT_MAX;
// Check whether a valid window of the given length exists
auto isValid = [&](int len) {
vector<int> freq(26, 0);
// Check the first window
for (int i = 0; i < len; i++)
freq[s[i] - 'a']++;
auto containsAll = [&]() {
for (int k = 0; k < 26; k++)
{
if (freq[k] < need[k])
return false;
}
return true;
};
if (containsAll())
return 0;
// Slide the window through s
for (int i = len; i < n; i++)
{
freq[s[i] - 'a']++;
freq[s[i - len] - 'a']--;
if (containsAll())
return i - len + 1;
}
return -1;
};
// Apply binary search on the window length
while (low <= high)
{
int mid = low + (high - low) / 2;
int idx = isValid(mid);
if (idx != -1)
{
// Store the valid window and search for a smaller one
start = idx;
minLen = mid;
high = mid - 1;
}
else
{
// Search for a larger window
low = mid + 1;
}
}
// Return an empty string if no valid window exists
if (start == -1)
return "";
// Return the smallest valid substring
return s.substr(start, minLen);
}
int main()
{
string s = "zoomlazapzo", p = "oza";
cout << "\"" << minWindow(s, p) << "\"" << endl;
return 0;
}
#include <limits.h>
#include <stdio.h>
#include <string.h>
// Check whether a window of the given length exists
int isValid(char *s, int n, int len, int need[])
{
int freq[26] = {0};
// Check the first window
for (int i = 0; i < len; i++)
freq[s[i] - 'a']++;
// Check whether all required characters are present
int valid = 1;
for (int k = 0; k < 26; k++)
{
if (freq[k] < need[k])
{
valid = 0;
break;
}
}
if (valid)
return 0;
// Slide the window through s
for (int i = len; i < n; i++)
{
freq[s[i] - 'a']++;
freq[s[i - len] - 'a']--;
valid = 1;
for (int k = 0; k < 26; k++)
{
if (freq[k] < need[k])
{
valid = 0;
break;
}
}
if (valid)
return i - len + 1;
}
return -1;
}
char *minWindow(char *s, char *p)
{
int n = strlen(s);
int m = strlen(p);
// If s is shorter than p, no valid window is possible
if (n < m)
return "";
// Store the frequency of characters in p
int need[26] = {0};
for (int i = 0; i < m; i++)
need[p[i] - 'a']++;
int low = m, high = n;
int start = -1, minLen = INT_MAX;
// Apply binary search on the window length
while (low <= high)
{
int mid = low + (high - low) / 2;
int idx = isValid(s, n, mid, need);
if (idx != -1)
{
// Store the valid window and search for a smaller one
start = idx;
minLen = mid;
high = mid - 1;
}
else
{
// Search for a larger window
low = mid + 1;
}
}
// Return an empty string if no valid window exists
if (start == -1)
return "";
// Create and return the smallest substring
static char result[100000];
strncpy(result, s + start, minLen);
result[minLen] = '\0';
return result;
}
int main()
{
char s[] = "zoomlazapzo";
char p[] = "oza";
printf("\"%s\"\n", minWindow(s, p));
return 0;
}
import java.util.Arrays;
public class GFG {
static int[] need;
// Check whether the window contains all required characters
static boolean containsAll(int[] freq) {
for (int k = 0; k < 26; k++) {
if (freq[k] < need[k])
return false;
}
return true;
}
// Check whether a valid window of the given length exists
static int isValid(String s, int len) {
int n = s.length();
int[] freq = new int[26];
// Check the first window
for (int i = 0; i < len; i++)
freq[s.charAt(i) - 'a']++;
if (containsAll(freq))
return 0;
// Slide the window through s
for (int i = len; i < n; i++) {
freq[s.charAt(i) - 'a']++;
freq[s.charAt(i - len) - 'a']--;
if (containsAll(freq))
return i - len + 1;
}
return -1;
}
public static String minWindow(String s, String p) {
int n = s.length(), m = p.length();
// If s is shorter than p, no valid window is possible
if (n < m)
return "";
// Store the frequency of characters in p
need = new int[26];
for (char c : p.toCharArray())
need[c - 'a']++;
int low = m, high = n;
int start = -1, minLen = Integer.MAX_VALUE;
// Apply binary search on the window length
while (low <= high) {
int mid = low + (high - low) / 2;
int idx = isValid(s, mid);
if (idx != -1) {
// Store the valid window and search for a smaller one
start = idx;
minLen = mid;
high = mid - 1;
} else {
// Search for a larger window
low = mid + 1;
}
}
// Return an empty string if no valid window exists
if (start == -1)
return "";
// Return the smallest valid substring
return s.substring(start, start + minLen);
}
public static void main(String[] args) {
String s = "zoomlazapzo", p = "oza";
System.out.println("\"" + minWindow(s, p) + "\"");
}
}
def minWindow(s, p):
n = len(s)
m = len(p)
# If s is shorter than p, no valid window is possible
if n < m:
return ""
# Store the frequency of characters in p
need = [0] * 26
for c in p:
need[ord(c) - ord('a')] += 1
low = m
high = n
start = -1
minLen = float('inf')
# Check whether a valid window of the given length exists
def isValid(length):
freq = [0] * 26
# Check the first window
for i in range(length):
freq[ord(s[i]) - ord('a')] += 1
def containsAll():
for k in range(26):
if freq[k] < need[k]:
return False
return True
if containsAll():
return 0
# Slide the window through s
for i in range(length, n):
freq[ord(s[i]) - ord('a')] += 1
freq[ord(s[i - length]) - ord('a')] -= 1
if containsAll():
return i - length + 1
return -1
# Apply binary search on the window length
while low <= high:
mid = low + (high - low) // 2
idx = isValid(mid)
if idx!= -1:
# Store the valid window and search for a smaller one
start = idx
minLen = mid
high = mid - 1
else:
# Search for a larger window
low = mid + 1
# Return an empty string if no valid window exists
if start == -1:
return ""
# Return the smallest valid substring
return s[start:start + minLen]
if __name__ == '__main__':
s = "zoomlazapzo"
p = "oza"
print(f'"{minWindow(s, p)}"')
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG {
public static string minWindow(string s, string p)
{
int n = s.Length, m = p.Length;
// If s is shorter than p, no valid window is
// possible
if (n < m)
return "";
// Store the frequency of characters in p
int[] need = new int[26];
foreach(char c in p) need[c - 'a']++;
int low = m, high = n;
int start = -1, minLen = int.MaxValue;
// Check whether a valid window of the given length
// exists
Func<int, int> isValid = (int len) =>
{
int[] freq = new int[26];
// Check the first window
for (int i = 0; i < len; i++)
freq[s[i] - 'a']++;
Func<bool> containsAll = () =>
{
for (int k = 0; k < 26; k++) {
if (freq[k] < need[k])
return false;
}
return true;
};
if (containsAll())
return 0;
// Slide the window through s
for (int i = len; i < n; i++) {
freq[s[i] - 'a']++;
freq[s[i - len] - 'a']--;
if (containsAll())
return i - len + 1;
}
return -1;
};
// Apply binary search on the window length
while (low <= high) {
int mid = low + (high - low) / 2;
int idx = isValid(mid);
if (idx != -1) {
// Store the valid window and search for a
// smaller one
start = idx;
minLen = mid;
high = mid - 1;
}
else {
// Search for a larger window
low = mid + 1;
}
}
// Return an empty string if no valid window exists
if (start == -1)
return "";
// Return the smallest valid substring
return s.Substring(start, minLen);
}
public static void Main()
{
string s = "zoomlazapzo";
string p = "oza";
Console.WriteLine("\"" + minWindow(s, p) + "\"");
}
}
function minWindow(s, p)
{
let n = s.length, m = p.length;
// If s is shorter than p, no valid window is possible
if (n < m)
return "";
// Store the frequency of characters in p
let need = new Array(26).fill(0);
for (let c of p)
need[c.charCodeAt(0) - "a".charCodeAt(0)]++;
let low = m, high = n;
let start = -1, minLen = Number.MAX_SAFE_INTEGER;
// Check whether a valid window of the given length
// exists
const isValid = (len) => {
let freq = new Array(26).fill(0);
// Check the first window
for (let i = 0; i < len; i++)
freq[s[i].charCodeAt(0) - "a".charCodeAt(0)]++;
const containsAll = () => {
for (let k = 0; k < 26; k++) {
if (freq[k] < need[k])
return false;
}
return true;
};
if (containsAll())
return 0;
// Slide the window through s
for (let i = len; i < n; i++) {
freq[s[i].charCodeAt(0) - "a".charCodeAt(0)]++;
freq[s[i - len].charCodeAt(0)
- "a".charCodeAt(0)]--;
if (containsAll())
return i - len + 1;
}
return -1;
};
// Apply binary search on the window length
while (low <= high) {
let mid = Math.floor(low + (high - low) / 2);
let idx = isValid(mid);
if (idx != -1) {
// Store the valid window and search for a
// smaller one
start = idx;
minLen = mid;
high = mid - 1;
}
else {
// Search for a larger window
low = mid + 1;
}
}
// Return an empty string if no valid window exists
if (start == -1)
return "";
// Return the smallest valid substring
return s.substring(start, start + minLen);
}
// Driver Code
let s = "zoomlazapzo";
let p = "oza";
console.log("\"" + minWindow(s, p) + "\"");
Output
"apzo"
[Expected Approach] Sliding Window - O(n) Time and O(1) Space
The idea is to maintain a window,
- Expand window from right end when some characters are yet to be included.
- Shrink the window from left end when all characters are already found.
Working of Approach:
- Store the frequency of every character in p.
- Expand the window by moving the right pointer and update its frequency.
- Increase the matched count when a required character occurrence is included.
- When all characters are matched, shrink the window from the left as much as possible.
- Update the minimum window and return the substring, or an empty string if no valid window exists.
Let us understand with an example:
#include <climits>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string minWindow(string &s, string &p)
{
int len1 = s.length();
int len2 = p.length();
// If s is shorter than p, no valid window is possible
if (len1 < len2)
return "";
vector<int> countP(256, 0);
vector<int> countS(256, 0);
// Store the frequency of characters in p
for (int i = 0; i < len2; i++)
countP[p[i]]++;
int start = 0, start_idx = -1, min_len = INT_MAX;
int count = 0;
// Expand the window using the right pointer
for (int j = 0; j < len1; j++)
{
countS[s[j]]++;
// Count only required character occurrences
if (countP[s[j]] != 0 && countS[s[j]] <= countP[s[j]])
{
count++;
}
// When all required characters are matched
if (count == len2)
{
// Shrink the window from the left
while (countS[s[start]] > countP[s[start]] || countP[s[start]] == 0)
{
if (countS[s[start]] > countP[s[start]])
countS[s[start]]--;
start++;
}
// Update the smallest valid window
int len = j - start + 1;
if (len < min_len)
{
min_len = len;
start_idx = start;
}
}
}
// Return an empty string if no valid window exists
if (start_idx == -1)
return "";
return s.substr(start_idx, min_len);
}
int main()
{
string s = "zoomlazapzo", p = "oza";
cout << "\"" << minWindow(s, p) << "\"" << endl;
return 0;
}
#include <limits.h>
#include <stdio.h>
#include <string.h>
char *minWindow(char *s, char *p)
{
int len1 = strlen(s);
int len2 = strlen(p);
// If s is shorter than p, no valid window is possible
if (len1 < len2)
return "";
int countP[256] = {0};
int countS[256] = {0};
// Store the frequency of characters in p
for (int i = 0; i < len2; i++)
countP[(unsigned char)p[i]]++;
int start = 0, start_idx = -1;
int min_len = INT_MAX;
int count = 0;
// Expand the window using the right pointer
for (int j = 0; j < len1; j++)
{
unsigned char c = (unsigned char)s[j];
countS[c]++;
// Count only required character occurrences
if (countP[c] != 0 && countS[c] <= countP[c])
count++;
// When all required characters are matched
if (count == len2)
{
// Shrink the window from the left
while (countS[(unsigned char)s[start]] > countP[(unsigned char)s[start]] ||
countP[(unsigned char)s[start]] == 0)
{
unsigned char left = (unsigned char)s[start];
if (countS[left] > countP[left])
countS[left]--;
start++;
}
// Update the smallest valid window
int len = j - start + 1;
if (len < min_len)
{
min_len = len;
start_idx = start;
}
}
}
// Return an empty string if no valid window exists
if (start_idx == -1)
return "";
// Create and return the smallest substring
static char result[100000];
strncpy(result, s + start_idx, min_len);
result[min_len] = '\0';
return result;
}
int main()
{
char s[] = "zoomlazapzo";
char p[] = "oza";
printf("\"%s\"\n", minWindow(s, p));
return 0;
}
import java.util.Arrays;
public class GFG {
public static String minWindow(String s, String p)
{
int len1 = s.length();
int len2 = p.length();
// If s is shorter than p, no valid window is
// possible
if (len1 < len2)
return "";
int[] countP = new int[256];
int[] countS = new int[256];
// Store the frequency of characters in p
for (int i = 0; i < len2; i++)
countP[p.charAt(i)]++;
int start = 0, start_idx = -1,
min_len = Integer.MAX_VALUE;
int count = 0;
// Expand the window using the right pointer
for (int j = 0; j < len1; j++) {
countS[s.charAt(j)]++;
// Count only required character occurrences
if (countP[s.charAt(j)] != 0
&& countS[s.charAt(j)]
<= countP[s.charAt(j)]) {
count++;
}
// When all required characters are matched
if (count == len2) {
// Shrink the window from the left
while (countS[s.charAt(start)]
> countP[s.charAt(start)]
|| countP[s.charAt(start)] == 0) {
if (countS[s.charAt(start)]
> countP[s.charAt(start)])
countS[s.charAt(start)]--;
start++;
}
// Update the smallest valid window
int len = j - start + 1;
if (len < min_len) {
min_len = len;
start_idx = start;
}
}
}
// Return an empty string if no valid window exists
if (start_idx == -1)
return "";
return s.substring(start_idx, start_idx + min_len);
}
public static void main(String[] args)
{
String s = "zoomlazapzo";
String p = "oza";
System.out.println("\"" + minWindow(s, p) + "\"");
}
}
def minWindow(s, p):
len1 = len(s)
len2 = len(p)
# If s is shorter than p, no valid window is possible
if len1 < len2:
return ""
countP = [0] * 256
countS = [0] * 256
# Store the frequency of characters in p
for i in range(len2):
countP[ord(p[i])] += 1
start = 0
start_idx = -1
min_len = float('inf')
count = 0
# Expand the window using the right pointer
for j in range(len1):
countS[ord(s[j])] += 1
# Count only required character occurrences
if countP[ord(s[j])]!= 0 and countS[ord(s[j])] <= countP[ord(s[j])]:
count += 1
# When all required characters are matched
if count == len2:
# Shrink the window from the left
while countS[ord(s[start])] > countP[ord(s[start])] or countP[ord(s[start])] == 0:
if countS[ord(s[start])] > countP[ord(s[start])]:
countS[ord(s[start])] -= 1
start += 1
# Update the smallest valid window
len_window = j - start + 1
if len_window < min_len:
min_len = len_window
start_idx = start
# Return an empty string if no valid window exists
if start_idx == -1:
return ""
return s[start_idx:start_idx + min_len]
if __name__ == '__main__':
s = "zoomlazapzo"
p = "oza"
print(f'"{minWindow(s, p)}"')
using System;
public class GFG {
public static string minWindow(string s, string p)
{
int len1 = s.Length;
int len2 = p.Length;
// If s is shorter than p, no valid window is
// possible
if (len1 < len2)
return "";
int[] countP = new int[256];
int[] countS = new int[256];
// Store the frequency of characters in p
for (int i = 0; i < len2; i++)
countP[p[i]]++;
int start = 0, start_idx = -1,
min_len = Int32.MaxValue;
int count = 0;
// Expand the window using the right pointer
for (int j = 0; j < len1; j++) {
countS[s[j]]++;
// Count only required character occurrences
if (countP[s[j]] != 0
&& countS[s[j]] <= countP[s[j]]) {
count++;
}
// When all required characters are matched
if (count == len2) {
// Shrink the window from the left
while (countS[s[start]] > countP[s[start]]
|| countP[s[start]] == 0) {
if (countS[s[start]] > countP[s[start]])
countS[s[start]]--;
start++;
}
// Update the smallest valid window
int len = j - start + 1;
if (len < min_len) {
min_len = len;
start_idx = start;
}
}
}
// Return an empty string if no valid window exists
if (start_idx == -1)
return "";
return s.Substring(start_idx, min_len);
}
public static void Main()
{
string s = "zoomlazapzo";
string p = "oza";
Console.WriteLine("\"" + minWindow(s, p) + "\"");
}
}
function minWindow(s, p)
{
let len1 = s.length;
let len2 = p.length;
// If s is shorter than p, no valid window is possible
if (len1 < len2)
return "";
let countP = new Array(256).fill(0);
let countS = new Array(256).fill(0);
// Store the frequency of characters in p
for (let i = 0; i < len2; i++)
countP[p.charCodeAt(i)]++;
let start = 0, start_idx = -1,
min_len = Number.MAX_VALUE;
let count = 0;
// Expand the window using the right pointer
for (let j = 0; j < len1; j++) {
countS[s.charCodeAt(j)]++;
// Count only required character occurrences
if (countP[s.charCodeAt(j)] != 0
&& countS[s.charCodeAt(j)]
<= countP[s.charCodeAt(j)]) {
count++;
}
// When all required characters are matched
if (count == len2) {
// Shrink the window from the left
while (countS[s.charCodeAt(start)]
> countP[s.charCodeAt(start)]
|| countP[s.charCodeAt(start)] == 0) {
if (countS[s.charCodeAt(start)]
> countP[s.charCodeAt(start)])
countS[s.charCodeAt(start)]--;
start++;
}
// Update the smallest valid window
let len = j - start + 1;
if (len < min_len) {
min_len = len;
start_idx = start;
}
}
}
// Return an empty string if no valid window exists
if (start_idx == -1)
return "";
return s.substring(start_idx, start_idx + min_len);
}
// Driver Code
let s = "zoomlazapzo";
let p = "oza";
console.log("\"" + minWindow(s, p) + "\"");
Output
"apzo"