Given a string S of size N consisting of the characters 0, 1 and 2, the task is to find the length of the smallest substring of string S that contains all the three characters 0, 1 and 2. If no such substring exists, then return -1.
Examples:
Input: S = "01212"
Output: 3
Explanation: The substring 012 is the smallest substring that contains the characters 0, 1 and 2.Input: S = "12121"
Output: -1
Explanation: As the character 0 is not present in the string S, therefore no substring containing all the three characters 0, 1 and 2 exists. Hence, the answer is -1 in this case.
Table of Content
[Approach - 1] Index Tracking - O(n) Time and O(1) Space
Keep track of the last seen indices of
'0','1', and'2'while iterating through the string. Once all three characters are found, compute the substring length as the difference between the maximum and minimum of the three indices. Update the minimum length found and return the result.
Illustration with Example:
#include <bits/stdc++.h>
using namespace std;
int smallestSubstring(string &S)
{
int res = INT_MAX;
// To check 0, 1 and 2
bool zero = false, one = false, two = false;
// To store indexes of 0, 1 and 2
int zeroindex, oneindex, twoindex;
for (int i = 0; i < S.length(); i++) {
if (S[i] == '0') {
zero = true;
zeroindex = i;
}
else if (S[i] == '1') {
one = true;
oneindex = i;
}
else if (S[i] == '2') {
two = true;
twoindex = i;
}
// Calculating length
if (zero and one and two)
res = min(res,
max({ zeroindex, oneindex, twoindex })
- min({ zeroindex, oneindex, twoindex }));
}
// In case if there is no substring that contains 0,1 and 2
if (res == INT_MAX)
return -1;
return res + 1;
}
// Driver Code
int main()
{
string S = "01212";
// Function call
cout << smallestSubstring(S);
return 0;
}
// This code is contributed by Aditya Kumar (adityakumar129)
// C program for above approach
#include <limits.h> // to use INT_MAX
#include <stdbool.h> //to use bool variable
#include <stdio.h>
// function to calculate max of two numbers
int min_two(int a, int b)
{
if (a <= b)
return a;
else
return b;
}
// function to calculate max of three numbers
int max_three(int a, int b, int c)
{
if (a >= b && a >= c)
return a;
else if (b > a && b >= c)
return b;
else if (c > a && c > b)
return c;
}
// function to calculate min of three numbers
int min_three(int a, int b, int c)
{
if (a <= b && a <= c)
return a;
else if (b < a && b <= c)
return b;
else if (c < a && c < b)
return c;
}
// Function to find the length of
// the smallest substring
int smallestSubstring(char S[])
{
int res = INT_MAX;
int n = strlen(S);
// To check 0, 1 and 2
bool zero = 0, one = 0, two = 0;
// To store indexes of 0, 1 and 2
int zeroindex, oneindex, twoindex;
for (int i = 0; i < n; i++) {
if (S[i] == '0') {
zero = true;
zeroindex = i;
}
else if (S[i] == '1') {
one = true;
oneindex = i;
}
else if (S[i] == '2') {
two = true;
twoindex = i;
}
// Calculating length
if (zero && one && two)
res = min_two( res,
max_three(zeroindex, oneindex, twoindex)
- min_three(zeroindex, oneindex, twoindex));
}
// In case if there is no substring that contains 0,1 and 2
if (res == INT_MAX)
return -1;
return res + 1;
}
// Driver Code
int main()
{
char S[] = "01212";
int ans = smallestSubstring(S);
// Function call
printf("%d", ans);
return 0;
}
// This code is contributed by Aditya Kumar (adityakumar129)
// Java program for above approach
import java.util.*;
class GfG {
// Function to find the length of the smallest substring
public static int smallestSubstring(String S)
{
int res = Integer.MAX_VALUE;
// To check 0, 1 and 2
boolean zero = false, one = false, two = false;
// To store indexes of 0, 1 and 2
int zeroindex = 0, oneindex = 0, twoindex = 0;
for (int i = 0; i < S.length(); i++) {
if (S.charAt(i) == '0') {
zero = true;
zeroindex = i;
}
else if (S.charAt(i) == '1') {
one = true;
oneindex = i;
}
else if (S.charAt(i) == '2') {
two = true;
twoindex = i;
}
// Calculating length
if (zero && one && two)
res = Math.min( res,
Math.max(zeroindex,Math.max(oneindex, twoindex))
- Math.min( zeroindex,Math.min(oneindex, twoindex)));
}
// In case if there is no substring that contains 0,1 and 2
if (res == Integer.MAX_VALUE)
return -1;
return res + 1;
}
// Driver Code
public static void main(String[] args)
{
String S = "01212";
// Function call
System.out.print(smallestSubstring(S));
}
}
def smallestSubstring(S):
res = 999999
# To check 0, 1 and 2
zero = 0
one = 0
two = 0
zeroindex = 0
oneindex = 0
twoindex = 0
for i in range(len(S)):
if (S[i] == '0'):
zero = 1
zeroindex = i
elif (S[i] == '1'):
one = 1
oneindex = i
elif (S[i] == '2'):
two = 1
twoindex = i
# Calculating length
if (zero and one and two):
res = min(res,
max([zeroindex, oneindex, twoindex])
- min([zeroindex, oneindex, twoindex]))
if (res == 999999):
return -1
return res + 1
# Driver Code
S = "01212"
# Function call
print(smallestSubstring(S))
// C# program for above approach
using System;
public class GfG {
// Function to find the length of the smallest substring
static int smallestSubstring(string S)
{
int res = Int32.MaxValue;
// To check 0, 1 and 2
bool zero = false, one = false, two = false;
// To store indexes of 0, 1 and 2
int zeroindex = 0, oneindex = 0, twoindex = 0;
for (int i = 0; i < S.Length; i++) {
if (S[i] == '0') {
zero = true;
zeroindex = i;
}
else if (S[i] == '1') {
one = true;
oneindex = i;
}
else if (S[i] == '2') {
two = true;
twoindex = i;
}
// Calculating length
if (zero && one && two)
res = Math.Min(res,
Math.Max( zeroindex, Math.Max(oneindex, twoindex))
- Math.Min( zeroindex, Math.Min(oneindex, twoindex)));
}
// In case if there is no substring that contains 0,1 and 2
if (res == Int32.MaxValue)
return -1;
return res + 1;
}
// Driver Code
static public void Main()
{
string S = "01212";
// Function call
Console.Write(smallestSubstring(S));
}
}
const smallestSubstring = (S) => {
let res = 9999999;
// To check 0, 1 and 2
let zero = false, one = false, two = false;
// To store indexes of 0, 1 and 2
let zeroindex, oneindex, twoindex;
for (let i = 0; i < S.length; i++) {
if (S[i] == "0") {
zero = true;
zeroindex = i;
}
else if (S[i] == "1") {
one = true;
oneindex = i;
}
else if (S[i] == "2") {
two = true;
twoindex = i;
}
// Calculating length
if (zero && one && two)
res = Math.min(res,
Math.max(...[zeroindex, oneindex, twoindex])
- Math.min(...[zeroindex, oneindex, twoindex]));
}
// In case if there is no substring that contains 0,1 and 2
if (res == 9999999)
return -1;
return res + 1;
}
// Driver Code
let S = "01212";
// Function call
console.log(smallestSubstring(S));
Output
3
[Approach - 2] Using a sliding window - O(n) Time and O(1) Space
Use two pointers (
iandk) and a frequency array to track the count of'0','1', and'2'. Expand the window by movingk, and when all three characters are present, shrink it from the left (i) to maintain the smallest valid substring. Return the minimum length found.
#include <bits/stdc++.h>
using namespace std;
int smallestSubstring(string &S) {
int n = S.length(), i = 0, j = 0, k = 0, cnt = 0, min_len = INT_MAX;
int freq[3] = {0};
while (k < n) {
freq[S[k]-'0']++;
if (freq[S[k]-'0'] == 1) cnt++;
if (cnt == 3) {
while (freq[S[i]-'0'] > 1) {
freq[S[i]-'0']--;
i++;
}
min_len = min(min_len, k-i+1);
freq[S[i]-'0']--;
i++;
cnt--;
}
k++;
}
return (min_len == INT_MAX) ? -1 : min_len;
}
int main() {
string S = "01212";
cout << smallestSubstring(S) << endl;
return 0;
}
import java.util.Arrays;
class GfG {
static int smallestSubstring(String S)
{
int n = S.length(), i = 0, j = 0, k = 0, cnt = 0,
min_len = Integer.MAX_VALUE;
int[] freq = new int[3];
Arrays.fill(freq, 0);
while (k < n) {
freq[S.charAt(k) - '0']++;
if (freq[S.charAt(k) - '0'] == 1)
cnt++;
if (cnt == 3) {
while (freq[S.charAt(i) - '0'] > 1) {
freq[S.charAt(i) - '0']--;
i++;
}
min_len = Math.min(min_len, k - i + 1);
freq[S.charAt(i) - '0']--;
i++;
cnt--;
}
k++;
}
return (min_len == Integer.MAX_VALUE) ? -1
: min_len;
}
public static void main(String[] args)
{
String S = "01212";
System.out.println(smallestSubstring(S));
}
}
def smallestSubstring(S):
# Initialize variables
n, i, j, k, cnt, min_len = len(S), 0, 0, 0, 0, float("inf")
# Frequency array
freq = [0] * 3
while k < n:
freq[int(S[k])] += 1
if freq[int(S[k])] == 1:
cnt += 1
if cnt == 3:
while freq[int(S[i])] > 1:
freq[int(S[i])] -= 1
i += 1
min_len = min(min_len, k - i + 1)
freq[int(S[i])] -= 1
i += 1
cnt -= 1
k += 1
return -1 if min_len == float("inf") else min_len
# Driver code
S = "01212"
print(smallestSubstring(S))
using System;
class GfG {
static int SmallestSubstring(string s)
{
int n = s.Length, i = 0, k = 0, cnt = 0,
min_len = int.MaxValue;
int[] freq = new int[3];
Array.Fill(freq, 0);
while (k < n) {
freq[s[k] - '0']++;
if (freq[s[k] - '0'] == 1)
cnt++;
if (cnt == 3) {
while (freq[s[i] - '0'] > 1) {
freq[s[i] - '0']--;
i++;
}
min_len = Math.Min(min_len, k - i + 1);
freq[s[i] - '0']--;
i++;
cnt--;
}
k++;
}
return (min_len == int.MaxValue) ? -1 : min_len;
}
public static void Main(string[] args)
{
string s = "01212";
Console.WriteLine(SmallestSubstring(s));
}
}
function smallestSubstring(S)
{
let n = S.length, i = 0, j = 0, k = 0, cnt = 0,
min_len = Infinity;
let freq = [ 0, 0, 0 ];
while (k < n) {
freq[parseInt(S[k])] += 1;
if (freq[parseInt(S[k])] == 1) {
cnt += 1;
}
if (cnt == 3) {
while (freq[parseInt(S[i])] > 1) {
freq[parseInt(S[i])] -= 1;
i += 1;
}
min_len = Math.min(min_len, k - i + 1);
freq[parseInt(S[i])] -= 1;
i += 1;
cnt -= 1;
}
k += 1;
}
return min_len == Infinity ? -1 : min_len;
}
// Driver code
let S = "01212";
// Function call
console.log(smallestSubstring(S));
Output
3