Given a string s consisting of the characters 0, 1 and 2, 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
Using Index Tracking - O(n) Time and O(1) Space
The idea is to 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 print the result.
#include <algorithm>
#include <climits>
#include <iostream>
#include <string>
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;
}
int main()
{
string s = "01212";
cout << smallestSubstring(s);
return 0;
}
#include <limits.h>
#include <stdbool.h>
#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;
}
int main()
{
char s[] = "01212";
int ans = smallestSubstring(s);
printf("%d", ans);
return 0;
}
import java.util.*;
class GfG {
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;
}
public static void main(String[] args)
{
String s = "01212";
System.out.print(smallestSubstring(s));
}
}
def smallestSubstring(s):
res = 999999
# To check 0, 1 and 2
zero = 0
one = 0
two = 0
# To store indexes of 0, 1 and 2
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]))
# In case if there is no substring that contains 0,1 and 2
if (res == 999999):
return -1
return res + 1
if __name__ == "__main__":
s = "01212"
print(smallestSubstring(s))
using System;
public class GfG {
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;
}
static public void Main()
{
string s = "01212";
Console.Write(smallestSubstring(s));
}
}
function 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";
console.log(smallestSubstring(s));
Output
3
Using a sliding window - O(n) Time and O(1) Space
The idea is to use two pointers (i and j) and a frequency array to track the count of '0', '1', and '2'. Expand the window by moving j, and when all three characters are present, shrink it from the left (i) to maintain the smallest valid substring. Print the minimum length found.
Dry run for string s = "01212":
- Initialize i = 0, j = 0, cnt = 0, min_len = INT_MAX and freq = {0, 0, 0}
- For j = 0, add '0': freq = {1, 0, 0}, cnt = 1 and cnt != 3 no update, expand window.
- For j = 1, add '1': freq = {1, 1, 0}, cnt = 2 and cnt != 3 no update, expand window.
- For j = 2, add '2': freq = {1, 1, 1}, cnt = 3. Now all digits are present hence, update min_len = min(INT_MAX, 2 - 0 + 1) = 3 and remove s[i] = '0': freq = {0, 1, 1}, increment i to 1, cnt = 2
- For j = 3, add '1': freq = {0, 2, 1}, cnt = 2 and cnt != 3 no update, expand window.
- For j = 4, add '2': freq = {0, 2, 2}, cnt = 2 and cnt != 3 no update, expand window.
So, final answer is min_len = 3.
#include <algorithm>
#include <climits>
#include <iostream>
#include <string>
using namespace std;
int smallestSubstring(string &s)
{
int n = s.length(), i = 0, j = 0, cnt = 0, min_len = INT_MAX;
// Stores frequency of digits 0, 1 and 2 inside current window
int freq[3] = {0};
while (j < n)
{
freq[s[j] - '0']++;
if (freq[s[j] - '0'] == 1)
cnt++;
// When all three digits are present, try to shrink the window
if (cnt == 3)
{
while (freq[s[i] - '0'] > 1)
{
freq[s[i] - '0']--;
i++;
}
// Update minimum length of valid substring
min_len = min(min_len, j - i + 1);
freq[s[i] - '0']--;
i++;
cnt--;
}
// Expand window by moving right pointer
j++;
}
return (min_len == INT_MAX) ? -1 : min_len;
}
int main()
{
string s = "01212";
cout << smallestSubstring(s) << endl;
return 0;
}
#include <stdio.h>
#include <limits.h>
int smallestSubstring(char *s)
{
int n = strlen(s), i = 0, j = 0, cnt = 0, min_len = INT_MAX;
// Stores frequency of digits 0, 1 and 2 inside current window
int freq[3] = {0};
while (j < n)
{
freq[s[j] - '0']++;
if (freq[s[j] - '0'] == 1)
cnt++;
// When all three digits are present, try to shrink the window
if (cnt == 3)
{
while (freq[s[i] - '0'] > 1)
{
freq[s[i] - '0']--;
i++;
}
// Update minimum length of valid substring
min_len = (min_len < j - i + 1)? min_len : j - i + 1;
freq[s[i] - '0']--;
i++;
cnt--;
}
// Expand window by moving right pointer
j++;
}
return (min_len == INT_MAX)? -1 : min_len;
}
int main()
{
char s[] = "01212";
printf("%d\n", smallestSubstring(s));
return 0;
}
import java.util.Arrays;
class GfG {
static int smallestSubstring(String s)
{
int n = s.length(), i = 0, j = 0, cnt = 0,
min_len = Integer.MAX_VALUE;
// Stores frequency of digits 0, 1 and 2 inside
// current window
int[] freq = new int[3];
Arrays.fill(freq, 0);
while (j < n) {
freq[s.charAt(j) - '0']++;
if (freq[s.charAt(j) - '0'] == 1)
cnt++;
// When all three digits are present, try to
// shrink the window
if (cnt == 3) {
while (freq[s.charAt(i) - '0'] > 1) {
freq[s.charAt(i) - '0']--;
i++;
}
// Update minimum length of valid substring
min_len = Math.min(min_len, j - i + 1);
freq[s.charAt(i) - '0']--;
i++;
cnt--;
}
// Expand window by moving right pointer
j++;
}
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):
n, i, j, cnt, min_len = len(s), 0, 0, 0, float('inf')
# Stores frequency of digits 0, 1 and 2 inside current window
freq = [0] * 3
while j < n:
freq[int(s[j])] += 1
if freq[int(s[j])] == 1:
cnt += 1
# When all three digits are present, try to shrink the window
if cnt == 3:
while freq[int(s[i])] > 1:
freq[int(s[i])] -= 1
i += 1
# Update minimum length of valid substring
min_len = min(min_len, j - i + 1)
freq[int(s[i])] -= 1
i += 1
cnt -= 1
# Expand window by moving right pointer
j += 1
return -1 if min_len == float('inf') else min_len
if __name__ == "__main__":
s = "01212"
print(smallestSubstring(s))
using System;
class GfG {
static int smallestSubstring(string s)
{
int n = s.Length, i = 0, j = 0, cnt = 0,
min_len = int.MaxValue;
// Stores frequency of digits 0, 1 and 2 inside
// current window
int[] freq = new int[3];
Array.Fill(freq, 0);
while (j < n) {
freq[s[j] - '0']++;
if (freq[s[j] - '0'] == 1)
cnt++;
// When all three digits are present, try to
// shrink the window
if (cnt == 3) {
while (freq[s[i] - '0'] > 1) {
freq[s[i] - '0']--;
i++;
}
// Update minimum length of valid substring
min_len = Math.Min(min_len, j - i + 1);
freq[s[i] - '0']--;
i++;
cnt--;
}
// Expand window by moving right pointer
j++;
}
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, cnt = 0,
min_len = Infinity;
let freq = [ 0, 0, 0 ];
while (j < n) {
freq[parseInt(s[j])] += 1;
if (freq[parseInt(s[j])] == 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, j - i + 1);
freq[parseInt(s[i])] -= 1;
i += 1;
cnt -= 1;
}
j += 1;
}
return min_len == Infinity ? -1 : min_len;
}
// Driver code
let s = "01212";
console.log(smallestSubstring(s));
Output
3