Removendo caracteres repetidos de uma string
1. Visão geral
Neste tutorial, discutiremos várias técnicas em Java sobre como remover caracteres repetidos de uma string.
Para cada técnica,we’ll also talk briefly about its time and space complexity.
2. Usandodistinct
Vamos começar removendo as duplicatas de nossa string usando o métododistinct introduzido no Java 8.
Abaixo, estamos obtendo uma instância deIntStream de um determinado objeto string. Então, estamos usando o métododistinct para remover as duplicatas. Por fim, estamos chamando o métodoforEach para percorrer os caracteres distintos e anexá-los ao nossoStringBuilder:
StringBuilder sb = new StringBuilder();
str.chars().distinct().forEach(c -> sb.append((char) c));
Time Complexity: O(n) - o tempo de execução do loop é diretamente proporcional ao tamanho da string de entrada
Auxiliary Space:O(n) - já quedistinct usa umLinkedHashSet internamente e também estamos armazenando a string resultante em um objetoStringBuilder
Maintains Order: Sim - já queLinkedHashSet mantém a ordem de seus elementos
E, embora seja bom que o Java 8 faça essa tarefa para nós tão bem, vamos compará-lo com os esforços para lançar o nosso próprio.
3. UsandoindexOf
A abordagem ingênua para remover duplicatas de uma string envolve simplesmentelooping over the input and using the indexOf method to check whether the current character already exists in the resulting string:
StringBuilder sb = new StringBuilder();
int idx;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
idx = str.indexOf(c, i + 1);
if (idx == -1) {
sb.append(c);
}
}
Time Complexity: O(n * n) - para cada caractere, o métodoindexOf percorre a string restante
Auxiliary Space:O(n) - espaço linear é necessário, uma vez que estamos usandoStringBuilder para armazenar o resultado
Maintains Order: Sim
Este método tem a mesma complexidade de espaço que a primeira abordagem, masperforms much slower.
4. Usando uma matriz de caracteres
Também podemos remover duplicatas de nossa string porconverting it into a char array and then looping over each character and comparing it to all subsequent characters.
Como podemos ver abaixo, estamos criando dois loopsfor e verificando se cada elemento é repetido na string. Se uma duplicata for encontrada, não a anexamos aoStringBuilder:
char[] chars = str.toCharArray();
StringBuilder sb = new StringBuilder();
boolean repeatedChar;
for (int i = 0; i < chars.length; i++) {
repeatedChar = false;
for (int j = i + 1; j < chars.length; j++) {
if (chars[i] == chars[j]) {
repeatedChar = true;
break;
}
}
if (!repeatedChar) {
sb.append(chars[i]);
}
}
Time Complexity: O(n * n) - temos um loop interno e um externo, ambos percorrendo a string de entrada
Auxiliary Space:O(n) - espaço linear é necessário uma vez que a variávelchars armazena uma nova cópia da entrada da string e também estamos usandoStringBuilder para salvar o resultado
Maintains Order: Sim
Novamente, nossa segunda tentativa tem um desempenho ruim em comparação com a oferta do Core Java, mas vamos ver onde chegamos com a próxima tentativa.
5. Usando a classificação
Como alternativa, caracteres repetidos podem ser eliminados classificando nossa string de entrada para agrupar duplicatas. In order to do that, we have to convert the string to a char array and sort it using the Arrays.sort method. Finally, we’ll iterate over the sorted char array.
Durante cada iteração, vamos comparar cada elemento da matriz com o elemento anterior. Se os elementos forem diferentes, adicionaremos o caractere atual aoStringBuilder:
StringBuilder sb = new StringBuilder();
if(!str.isEmpty()) {
char[] chars = str.toCharArray();
Arrays.sort(chars);
sb.append(chars[0]);
for (int i = 1; i < chars.length; i++) {
if (chars[i] != chars[i - 1]) {
sb.append(chars[i]);
}
}
}
Time Complexity: O(n log n) - a classificação usa umdual-pivot Quicksort que oferece desempenho O (n log n) em muitos conjuntos de dados
Auxiliary Space:O(n) - uma vez que o métodotoCharArray faz uma cópia da entradaString
Maintains Order: Não
Vamos tentar novamente com nossa tentativa final.
6. Usando umSet
Outra maneira de remover caracteres repetidos de uma string é por meio do uso deSet. If we do not care about the order of characters in our output string we can use a HashSet.Otherwise, we can use a LinkedHashSet to maintain the insertion order.
Em ambos os casos, faremos um loop na string de entrada e adicionaremos cada caractere aoSet. Uma vez que os caracteres são inseridos no conjunto, vamos iterar sobre ele para adicioná-los aoStringBuilder e retornar a string resultante:
StringBuilder sb = new StringBuilder();
Set linkedHashSet = new LinkedHashSet<>();
for (int i = 0; i < str.length(); i++) {
linkedHashSet.add(str.charAt(i));
}
for (Character c : linkedHashSet) {
sb.append(c);
}
Time Complexity: O(n) - o tempo de execução do loop é diretamente proporcional ao tamanho da string de entrada
Auxiliary Space:O(n) - o espaço necessário paraSet depende do tamanho da string de entrada; também, estamos usandoStringBuilder para armazenar o resultado
Maintains Order:LinkedHashSet – Sim,HashSet – Não
E agora, combinamos a abordagem do Core Java! Não é muito chocante descobrir que isso é muito semelhante ao quedistinct já faz.
7. Conclusão
In this article, we covered a few ways to remove repeated characters from a string in Java. Também observamos a complexidade de tempo e espaço de cada um desses métodos.
Como sempre, trechos de código podem ser encontradosover on GitHub.