Problema com String

lsjunior, o método contains tem dentro dele um for. Se a letra não existir no alfabeto, o texto inteiro será percorrido.

Portanto, seu método irá percorrer o texto inteiro para cada letra que não existir, e irá percorrer o texto do início até a primeira ocorrência das letras que existirem.
Isso repetido para cada letra do alfabeto.

O método que postei percorre o texto uma única vez, e testa simultaneamente todas as letras do alfabeto. Ele também não perde tempo verificando se a letra já existe ou não no array. E a contagem é apenas um benefício adicional. No primeiro exemplo, usei um boolean.

A única coisa que poderia ser usada para tornar o meu algoritmo mais eficiente, no caso de eliminar a contagem, é ter um contador para saber quantas letras já foram encontradas dentro do alfabeto. Quando esse contador chegar a 0, poderia interromper o algoritmo. Isso evitaria que o algoritmo perdesse tempo percorrendo um texto muito longo, caso todas as letras já tivessem sido encontradas.

Então lsjunior, aí é que está o problema!
Não temos 3 iterações pois pra você identificar os caracteres, você percorrerá a String inteira de qualquer forma.
Seja com for ou com contains.

Para cada letra que você for verificar será um novo for, ou seja, você percorrerá até que a letra seja encontrada.
Logo, você não teria somente 3 iterações.

Abraços!

Eu sei como funciona o indexOf. Fiz o exemplo para fins didaticos, por que enviar muito código um pouco complexo para um professor é o mesmo que dizer que não foi ele que fez. Existem ínumeras formas de resolver aquele problema e eu fiz da forma que achei o mais simples possível.

Pra quem duvida, eis a implementação dos métodos contains e indexOf:

/** * Returns true if and only if this string contains the specified * sequence of char values. * * @param s the sequence to search for * @return true if this string contains <code>s</code>, false otherwise * @throws NullPointerException if <code>s</code> is <code>null</code> * @since 1.5 */ public boolean contains(CharSequence s) { return indexOf(s.toString()) > -1; }

/** * Returns the index within this string of the first occurrence of the * specified substring. The integer returned is the smallest value * <i>k</i> such that: * <blockquote><pre> * this.startsWith(str, <i>k</i>) * </pre></blockquote> * is <code>true</code>. * * @param str any string. * @return if the string argument occurs as a substring within this * object, then the index of the first character of the first * such substring is returned; if it does not occur as a * substring, <code>-1</code> is returned. */ public int indexOf(String str) { return indexOf(str, 0); }

/** * Returns the index within this string of the first occurrence of the * specified substring, starting at the specified index. The integer * returned is the smallest value <tt>k</tt> for which: * <blockquote><pre> * k >= Math.min(fromIndex, this.length()) && this.startsWith(str, k) * </pre></blockquote> * If no such value of <i>k</i> exists, then -1 is returned. * * @param str the substring for which to search. * @param fromIndex the index from which to start the search. * @return the index within this string of the first occurrence of the * specified substring, starting at the specified index. */ public int indexOf(String str, int fromIndex) { return indexOf(value, offset, count, str.value, str.offset, str.count, fromIndex); }

Finalmente, aqui está o for escondido:

[code] /**
* Code shared by String and StringBuffer to do searches. The
* source is the character array being searched, and the target
* is the string being searched for.
*
* @param source the characters being searched.
* @param sourceOffset offset of the source string.
* @param sourceCount count of the source string.
* @param target the characters being searched for.
* @param targetOffset offset of the target string.
* @param targetCount count of the target string.
* @param fromIndex the index to begin searching from.
*/
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
}

    char first  = target[targetOffset];
    int max = sourceOffset + (sourceCount - targetCount);

    for (int i = sourceOffset + fromIndex; i <= max; i++) {
        /* Look for first character. */
        if (source[i] != first) {
            while (++i <= max && source[i] != first);
        }

        /* Found first character, now look at the rest of v2 */
        if (i <= max) {
            int j = i + 1;
            int end = j + targetCount - 1;
            for (int k = targetOffset + 1; j < end && source[j] ==
                     target[k]; j++, k++);

            if (j == end) {
                /* Found whole string. */
                return i - sourceOffset;
            }
        }
    }
    return -1;
}[/code]

Poxa, de vez em quando escrevo enquanto o Vinny também está postando e acabo
falando algo parecido. Sorry!

Mas o Vinny explicou também a idéia do algoritmo dele! :slight_smile:

Até mais!

E o que tem de complexo no meu código? É um uso básico da tabela ascii.
Não envolve concatenação de Strings, ou uso de métodos específicos da API.

Provavelmente é o que o professor está esperando, se ele ensinou como o char funciona.

[quote]E o que tem de complexo no meu código? É um uso básico da tabela ascii.
Provavelmente é o que o professor está esperando, se ele ensinou como o char funciona.[/quote]

Isso que quis dizer lsjunior sobre as minhas antigas aulas de C na faculdade.
Normalmente o professor ensina o conceito de char e pede exatamente como o Vinny falou.

Na verdade nem estava discutindo o seu código em si, somente dei um toque sobre as iterações
que você mencionou.

Abraços!

Certo.

Pra quem não entendeu como meu código funciona.

Toda caracter, em java, é também um número. Esse número é baseado numa tabela, chamada Unicode (antigamente Ascii). Se você consultar essa tabela, verá que lá o valor da letra A é 65, B é 66, C é 67 e assim por diante.

O código então cria um array de letras encontradas, com posição de 0 até 25 (uma para cada letra do alfabeto).

Quando encontro uma letra, subtraio 65 do seu valor. Isso fará com que eu obtenha 0 para a letra A (que vale 65), 1 para letra B, 2 para a letra C, e assim por diante. Esse é o índice da letra no array das letras encontradas. Com esse índice na mão, basta marcar ali “true” indicando que achei a letra.

O mesmo processo funciona para contagem. A única diferença é que ao invés do array representar letras encontradas, eu apenas somo 1 à contagem.

O código aparentemente é mais complexo por ter uma continha de menos simples, e por considerar o valor ascii da letra. Claro, se você não conhece essa tabela, ele será ininteligível. Vai da matéria que seu professor está passando.