Show the amount of each alphabet letter in a String

Asked

Viewed 843 times

3

I’m doing an exercise in Java where the user enters with a sentence. After that, I have to list how many letters there are in the sentence, for example:

Input = Daniel Henrique
Exit:

A = 1 B = 0 C = 0 D = 1 ... Z = 0

Follows code:

String frase = "";
int n = 0;
int c = 97;
int letra = 0;
int qtdn = 0;

System.out.print("Frase: ");
frase = leia.nextLine();

for (int i = 0; i < frase.length(); i++) {
    while (c <= 122) {
        if (frase.toLowerCase().charAt(i) == (char) c) {
            qtdn++;
        }
        System.out.println((char) c + " = " + qtdn);
        c++;
    }

}

3 answers

3

What you can do is reverse the order of the loops, ie for each letter of the alphabet you count in the sentence how many there are, see the example below:

        String frase = "Daniel Henrique";
        int n = 0;
        int c = 97;
        int letra = 0;

        System.out.print("Frase: ");
        frase = leia.nextLine();

        while (c <= 122) {
            int qtdn = 0;
            for (int i = 0; i < frase.length(); i++) {
                if (frase.toLowerCase().charAt(i) == (char) c) {
                    qtdn++;
                }
            }
            System.out.println((char) c + " = " + qtdn);
            c++;

        }

    }

3

You don’t have to make a loop within another, for this is very inefficient: for each character of the String, you want to compare it to each of the 26 letters, then at the end you will be doing N * 26 iterations (being N the size of String).

You can do all this by going through String a single time. Simply create an array containing the count of each letter, and update it as you go through the String.

Then you make another loop to show the quantities of each letter:

String frase = "Daniel Henrique";
int[] quantidades = new int[26];

for (char c : frase.toUpperCase().toCharArray()) {
    int indice = c - 65;
    if (indice >= 0 && indice < 26) {
        quantidades[indice] += 1;
    }
}

for (int i = 0; i < quantidades.length; i++) {
    char letra = (char) (i + 65);
    System.out.println(letra + "=" + quantidades[i]);
}

First I create an array containing the quantities of each letter, so it has 26 positions. I take advantage of the fact that in Java, an array of int created this way is already initialized with zero at all positions (which is just what we need, because at the beginning the amount of any letter is zero, since I haven’t started counting).

In the first for I go through the String. Your code implied that it doesn’t matter if the letters are uppercase or lowercase, so I’m capitalizing (toUpperCase()).

For each character, I check if it is a letter of A to Z (by subtracting 65 from a char, if this is a letter from A to Z, the result will be between zero and 25, which is a valid position in the quantity array). If it is, I add 1 in the respective quantity.

In the second for i print the letters and their respective quantities. In the end, I just went through the String and quantities once, totalling N + 26 iterations (being N the size of String) - much better than making a loop within another, which as already said, generates N * 26 iterations.

2


I decided to answer because I did not like the current solutions, although certain. In general the staff does not program thinking about performance. In such an algorithm that can be used over and over again can cause great damage and then people blame Java for consuming too much memory. In a solution (the currently accepted) makes an allocation of string without need, and the other (the most voted currently) makes two allocations, which generates pressure on the Garbage Collector, then I take each character locally and manipulate it, eliminating unnecessary allocations. It may look like it has more processing, but you’ll see what’s inside those used functions, you’re using up to 3 loops without even realizing it:

class Main {
    public static void main (String[] args) {
        String frase = "Daniel Henrique";
        int[] quantidades = new int[26];
        for (int i = 0; i < frase.length(); i++) {
            if (frase.charAt(i) > 64 && frase.charAt(i) < 91) quantidades[frase.charAt(i) - 65]++;
            if (frase.charAt(i) > 96 && frase.charAt(i) < 123) quantidades[frase.charAt(i) - 97]++;
        }
        for (int i = 0; i < quantidades.length; i++) System.out.println((char)(i + 65) + " => " + quantidades[i]);
    }
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

  • These two checks (from 65 to 90 && 97 to 122) is to check the right uppercase and lowercase?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.