Contar substrings com k caracteres distintos
Dada uma string s consistindo apenas de letras minúsculas em inglês e um número inteiro k, conte o número total de substrings (não necessariamente distintas) de s que contêm exatamente k caracteres distintos.
Observação:
- Uma substring é uma sequência contígua de caracteres dentro de uma string.
- Substrings que são idênticas, mas ocorrem em posições diferentes, devem ser contadas separadamente.
Exemplos:
Entrada: s = 'abc' k = 2
Saída: 2
Explicação: Substrings possíveis são ['ab' 'bc']Entrada: s = 'aba' k = 2
Saída: 3
Explicação: Substrings possíveis são ['ab' 'ba' 'aba']Entrada: s = 'AA' k = 1
Saída: 3
Explicação: Substrings possíveis são ['a' 'a' 'aa']
Índice
- [Abordagem ingênua] Verificando todas as substrings - tempo O (n ^ 2) e espaço O (1)
- [Abordagem Eficiente] Usando o Método de Janela Deslizante - O(n) tempo e O(1) espaço
[Abordagem ingênua] Verificando todas as substrings - tempo O (n ^ 2) e espaço O (1)
C++A ideia é verificar todas as substrings possíveis iterando todas as posições iniciais (i) e finais (j) possíveis na string. Para cada substring, mantenha uma matriz booleana para rastrear caracteres distintos e um contador para o número de caracteres distintos. À medida que expande a substring da esquerda para a direita, ele atualiza a contagem de caracteres distintos, verificando se cada novo caractere foi visto antes. Sempre que o número de caracteres distintos corresponder exatamente ao k fornecido, ele incrementará a contagem de respostas.
#include #include using namespace std ; int countSubstr ( string & s int k ) { int n = s . length (); int ans = 0 ; for ( int i = 0 ; i < n ; i ++ ) { // array to check if a character // is present in substring i..j vector < bool > map ( 26 0 ); int distinctCnt = 0 ; for ( int j = i ; j < n ; j ++ ) { // if new character is present // increment distinct count. if ( map [ s [ j ] - 'a' ] == false ) { map [ s [ j ] - 'a' ] = true ; distinctCnt ++ ; } // if distinct count is equal to k. if ( distinctCnt == k ) ans ++ ; } } return ans ; } int main () { string s = 'abc' ; int k = 2 ; cout < < countSubstr ( s k ); return 0 ; }
Java class GfG { static int countSubstr ( String s int k ) { int n = s . length (); int ans = 0 ; for ( int i = 0 ; i < n ; i ++ ) { // array to check if a character // is present in substring i..j boolean [] map = new boolean [ 26 ] ; int distinctCnt = 0 ; for ( int j = i ; j < n ; j ++ ) { // if new character is present // increment distinct count. if ( ! map [ s . charAt ( j ) - 'a' ] ) { map [ s . charAt ( j ) - 'a' ] = true ; distinctCnt ++ ; } // if distinct count is equal to k. if ( distinctCnt == k ) ans ++ ; } } return ans ; } public static void main ( String [] args ) { String s = 'abc' ; int k = 2 ; System . out . println ( countSubstr ( s k )); } }
Python def countSubstr ( s k ): n = len ( s ) ans = 0 for i in range ( n ): # array to check if a character # is present in substring i..j map = [ False ] * 26 distinctCnt = 0 for j in range ( i n ): # if new character is present # increment distinct count. if not map [ ord ( s [ j ]) - ord ( 'a' )]: map [ ord ( s [ j ]) - ord ( 'a' )] = True distinctCnt += 1 # if distinct count is equal to k. if distinctCnt == k : ans += 1 return ans if __name__ == '__main__' : s = 'abc' k = 2 print ( countSubstr ( s k ))
C# using System ; class GfG { static int countSubstr ( string s int k ) { int n = s . Length ; int ans = 0 ; for ( int i = 0 ; i < n ; i ++ ) { // array to check if a character // is present in substring i..j bool [] map = new bool [ 26 ]; int distinctCnt = 0 ; for ( int j = i ; j < n ; j ++ ) { // if new character is present // increment distinct count. if ( ! map [ s [ j ] - 'a' ]) { map [ s [ j ] - 'a' ] = true ; distinctCnt ++ ; } // if distinct count is equal to k. if ( distinctCnt == k ) ans ++ ; } } return ans ; } static void Main () { string s = 'abc' ; int k = 2 ; Console . WriteLine ( countSubstr ( s k )); } }
JavaScript function countSubstr ( s k ) { let n = s . length ; let ans = 0 ; for ( let i = 0 ; i < n ; i ++ ) { // array to check if a character // is present in substring i..j let map = new Array ( 26 ). fill ( false ); let distinctCnt = 0 ; for ( let j = i ; j < n ; j ++ ) { // if new character is present // increment distinct count. if ( ! map [ s . charCodeAt ( j ) - 'a' . charCodeAt ( 0 )]) { map [ s . charCodeAt ( j ) - 'a' . charCodeAt ( 0 )] = true ; distinctCnt ++ ; } // if distinct count is equal to k. if ( distinctCnt === k ) ans ++ ; } } return ans ; } // Driver Code let s = 'abc' ; let k = 2 ; console . log ( countSubstr ( s k ));
Saída
2
[Abordagem Eficiente] Usando o Método de Janela Deslizante - O(n) tempo e O(1) espaço
A ideia é usar janela deslizante técnica para contar substrings com eficiência com no máximo k caracteres distintos e, em seguida, subtrair a contagem de substrings com no máximo k-1 caracteres distintos para obter o número de substrings com exatamente k caracteres distintos.
Implementação passo a passo:
- Use uma janela deslizante com uma matriz de tamanho 26 para rastrear as frequências dos caracteres.
- Expanda a janela à direita adicionando caracteres.
- Reduza a janela da esquerda quando caracteres distintos excederem k.
- Conte todas as substrings válidas na janela.
- Subtraia substrings com k-1 caracteres distintos de k caracteres distintos.
#include #include using namespace std ; // function which finds the number of // substrings with atmost k Distinct // characters. int count ( string & s int k ) { int n = s . length (); int ans = 0 ; // use sliding window technique vector < int > freq ( 26 0 ); int distinctCnt = 0 ; int i = 0 ; for ( int j = 0 ; j < n ; j ++ ) { // expand window and add character freq [ s [ j ] - 'a' ] ++ ; if ( freq [ s [ j ] - 'a' ] == 1 ) distinctCnt ++ ; // shrink window if distinct characters exceed k while ( distinctCnt > k ) { freq [ s [ i ] - 'a' ] -- ; if ( freq [ s [ i ] - 'a' ] == 0 ) distinctCnt -- ; i ++ ; } // add number of valid substrings ending at j ans += j - i + 1 ; } return ans ; } // function to find the number of substrings // with exactly k Distinct characters. int countSubstr ( string & s int k ) { int n = s . length (); int ans = 0 ; // subtract substrings with at most // k-1 distinct characters from substrings // with at most k distinct characters ans = count ( s k ) - count ( s k -1 ); return ans ; } int main () { string s = 'abc' ; int k = 2 ; cout < < countSubstr ( s k ); return 0 ; }
Java class GfG { // function which finds the number of // substrings with atmost k Distinct // characters. static int count ( String s int k ) { int n = s . length (); int ans = 0 ; // use sliding window technique int [] freq = new int [ 26 ] ; int distinctCnt = 0 ; int i = 0 ; for ( int j = 0 ; j < n ; j ++ ) { // expand window and add character freq [ s . charAt ( j ) - 'a' ]++ ; if ( freq [ s . charAt ( j ) - 'a' ] == 1 ) distinctCnt ++ ; // shrink window if distinct characters exceed k while ( distinctCnt > k ) { freq [ s . charAt ( i ) - 'a' ]-- ; if ( freq [ s . charAt ( i ) - 'a' ] == 0 ) distinctCnt -- ; i ++ ; } // add number of valid substrings ending at j ans += j - i + 1 ; } return ans ; } // function to find the number of substrings // with exactly k Distinct characters. static int countSubstr ( String s int k ) { int n = s . length (); int ans = 0 ; // Subtract substrings with at most // k-1 distinct characters from substrings // with at most k distinct characters ans = count ( s k ) - count ( s k - 1 ); return ans ; } public static void main ( String [] args ) { String s = 'abc' ; int k = 2 ; System . out . println ( countSubstr ( s k )); } }
Python # function which finds the number of # substrings with atmost k Distinct # characters. def count ( s k ): n = len ( s ) ans = 0 # ese sliding window technique freq = [ 0 ] * 26 distinctCnt = 0 i = 0 for j in range ( n ): # expand window and add character freq [ ord ( s [ j ]) - ord ( 'a' )] += 1 if freq [ ord ( s [ j ]) - ord ( 'a' )] == 1 : distinctCnt += 1 # shrink window if distinct characters exceed k while distinctCnt > k : freq [ ord ( s [ i ]) - ord ( 'a' )] -= 1 if freq [ ord ( s [ i ]) - ord ( 'a' )] == 0 : distinctCnt -= 1 i += 1 # add number of valid substrings ending at j ans += j - i + 1 return ans # function to find the number of substrings # with exactly k Distinct characters. def countSubstr ( s k ): n = len ( s ) ans = 0 # subtract substrings with at most # k-1 distinct characters from substrings # with at most k distinct characters ans = count ( s k ) - count ( s k - 1 ) return ans if __name__ == '__main__' : s = 'abc' k = 2 print ( countSubstr ( s k ))
C# using System ; class GfG { // function which finds the number of // substrings with atmost k Distinct // characters. static int count ( string s int k ) { int n = s . Length ; int ans = 0 ; // use sliding window technique int [] freq = new int [ 26 ]; int distinctCnt = 0 ; int i = 0 ; for ( int j = 0 ; j < n ; j ++ ) { // expand window and add character freq [ s [ j ] - 'a' ] ++ ; if ( freq [ s [ j ] - 'a' ] == 1 ) distinctCnt ++ ; // shrink window if distinct characters exceed k while ( distinctCnt > k ) { freq [ s [ i ] - 'a' ] -- ; if ( freq [ s [ i ] - 'a' ] == 0 ) distinctCnt -- ; i ++ ; } // add number of valid substrings ending at j ans += j - i + 1 ; } return ans ; } // function to find the number of substrings // with exactly k Distinct characters. static int countSubstr ( string s int k ) { int n = s . Length ; int ans = 0 ; // subtract substrings with at most // k-1 distinct characters from substrings // with at most k distinct characters ans = count ( s k ) - count ( s k - 1 ); return ans ; } static void Main () { string s = 'abc' ; int k = 2 ; Console . WriteLine ( countSubstr ( s k )); } }
JavaScript // function which finds the number of // substrings with atmost k Distinct // characters. function count ( s k ) { let n = s . length ; let ans = 0 ; // use sliding window technique let freq = new Array ( 26 ). fill ( 0 ); let distinctCnt = 0 ; let i = 0 ; for ( let j = 0 ; j < n ; j ++ ) { // expand window and add character freq [ s . charCodeAt ( j ) - 'a' . charCodeAt ( 0 )] ++ ; if ( freq [ s . charCodeAt ( j ) - 'a' . charCodeAt ( 0 )] === 1 ) distinctCnt ++ ; // shrink window if distinct characters exceed k while ( distinctCnt > k ) { freq [ s . charCodeAt ( i ) - 'a' . charCodeAt ( 0 )] -- ; if ( freq [ s . charCodeAt ( i ) - 'a' . charCodeAt ( 0 )] === 0 ) distinctCnt -- ; i ++ ; } // add number of valid substrings ending at j ans += j - i + 1 ; } return ans ; } // sunction to find the number of substrings // with exactly k Distinct characters. function countSubstr ( s k ) { let n = s . length ; let ans = 0 ; // subtract substrings with at most // k-1 distinct characters from substrings // with at most k distinct characters ans = count ( s k ) - count ( s k - 1 ); return ans ; } // Driver Code let s = 'abc' ; let k = 2 ; console . log ( countSubstr ( s k ));
Saída
2