[BaekJoon] 10808번 - 알파벳 개수 (java)

1. 문제

👉 문제 바로가기

- 조건

시간 제한 메모리 제한
1초 256MB


- 문제

알파벳 소문자로만 이루어진 단어 S가 주어진다. 각 알파벳이 단어에 몇 개가 포함되어 있는지 구하는 프로그램을 작성하시오.



- 입력

첫째 줄에 단어 S가 주어진다. 단어의 길이는 100을 넘지 않으며, 알파벳 소문자로만 이루어져 있다.



- 출력

단어에 포함되어 있는 a의 개수, b의 개수, …, z의 개수를 공백으로 구분해서 출력한다.



- 예제

  입력      출력  
baekjoon 1 1 0 0 1 0 0 0 0 1 1 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0





2. 풀이


- 알고리즘

for 반복문을 사용해 입력받은 S 에 포함된 알파벳의 개수를 증가시키고, 알파벳의 개수를 저장한 배열을 출력한다.

for (초기식; 조건식; 증감식) {
    조건식의 결과가 참인 동안 반복적으로 실행하고자 하는 명령문 작성;
}




이번 문제는 아스키코드를 활용해야 한다!

  1. 아스키코드를 사용해 알파벳을 0-26 사이의 숫자로 변환한다.
  2. 해당 숫자에 맞는 배열 인덱스에 1씩 더한다.

아스키코드





2개의 입력방식을 사용해서 결과를 출력한다.

  1. Scanner 클래스
  2. BufferedReader 클래스





2-1. Scanner 클래스

import java.util.Scanner;

public class Main{
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        String S = sc.nextLine();
        
        int[] arr = new int[26]; // 알파벳의 개수를 저장하는 배열
        
        for(int i=0;i<S.length();i++){
            int a = S.charAt(i) - 97;
            arr[a]++;
        }
        
        for(int j=0;j<26;j++){
            System.out.print(arr[j] + " ");
        }
    }
}

위와같이 객체를 생성할 때, Scanner(System.in) 에서 System.in 은 입력한 값을 Byte 단위로 읽는 것을 뜻한다.

int형 데이터를 입력받기 위해 nextInt() 메서드를 사용한다.

charAt() 은 String으로 저장된 문자열에서 한 글자만 선택해서 char타입으로 변환해주는 메소드이다.
위의 아스키코드 표에서 소문자 알파벳은 97 ~ 122 사이이다.
따라서 S.charAt(i) 에서 97 을 빼면, 해당 알파벳 개수를 저장하는 배열의 인덱스를 구할 수 있다.



[여기서 잠깐!]

Scanner에 대해 더 자세히 알고싶다면 여기 를 클릭하세요




2-2. BufferedReader 클래스 사용

3가지 출력 방식으로 문제를 풀어보고 비교해보자.



     ① StringBuilder
     ② BufferedWriter
     ③ System.out.println()





① BufferedReader + StringBuilder

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main{
    public static void main(String args[]) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
        StringBuilder sb = new StringBuilder();
        String S = br.readLine();
        
        int[] arr = new int[26]; // 알파벳의 개수를 저장하는 배열
        
        for(int i=0;i<S.length();i++){
            int a = S.charAt(i) - 97;
            arr[a]++;
        }
        
        for(int j=0;j<26;j++){
            sb.append(arr[j]).append(" ");
        }
        System.out.println(sb);
    }
}

StringBuilder 클래스는 문자열을 동적으로 조작하기 위한 클래스로, append() 를 사용해 문자열을 추가하여 새로운 문자열을 생성한다.

append()sb.append(arr[j] + " ") 이렇게 쓰지 않고, 위와 같이 나눠서 쓰면 타입 변환과 문자열 연결 연산이 추가적으로 발생하지 않고 StringBuilder에 직접 추가하기 때문에 보다 더 효율적이고 빠르다.





② BufferedReader + BufferedWriter

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.IOException;

public class Main{
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        
        String S = br.readLine();
        br.close();
        
        int[] arr = new int[26]; // 알파벳의 개수를 저장하는 배열
        
        for(int i=0;i<S.length();i++){
            int a = S.charAt(i) - 97;
            arr[a]++;
        }
        
        for(int j=0;j<26;j++){
            bw.write(arr[j] + " ");
        }
        bw.flush();
        bw.close();
    }
}

BufferedWriter 클래스의 write() 메소드는 데이터를 내부 버퍼에 저장하고, flush() 메소드 를 사용해 버퍼를 비우고 데이터를 출력한다.

BufferedWriter 클래스의 write() 메소드는 단독으로 int 형 값만 넣을 경우 아스키 코드값으로 인식되기 때문에 다른 문자가 출력된다. 때문에 반드시 문자열과 int 형을 함께 넣어줘야 int 값을 제대로 출력할 수 있다.



[여기서 잠깐!]

BufferedWriter 클래스에 대해 더 알아보고 싶으면 여기를 클릭하면 된다.





③ BufferedReader + System.out.println()

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main{
    public static void main(String args[]) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
        String S = br.readLine();
        
        int[] arr = new int[26]; // 알파벳의 개수를 저장하는 배열
        
        for(int i=0;i<S.length();i++){
            int a = S.charAt(i) - 97;
            arr[a]++;
        }
        
        for(int j=0;j<26;j++){
            System.out.print(arr[j] + " ");
        }
    }
}





3. Scanner VS BufferedReader 성능 비교

image

위에서 부터 순서대로

BufferedReader + StringBuilder
BufferedReader + BufferedWriter
BufferedReader + System.out.println()
Scanner

위와같이 입력 메소드와 알고리즘 구현 방법에 따라 시간이 달라질 수 있다.

입력의 경우 확실히 Scanner 보다는 BufferedReader 가 빠른 것을 볼 수 있다.

출력의 경우 StringBuilder 가 가장 빠른 것을 볼 수 있다.
(그러나 데이터 양이 커지면 커질 수록 BufferedWriter 가 더 빠르다.)

BufferedWriter는 일반적으로 I/O 작업으로 인해 비교적 느릴 수 있다.
반면에 StringBuilder는 문자열 조작에 최적화된 클래스로, 문자열 연산은 일반적으로 메모리 상에서 수행되므로 상대적으로 빠를 수 있다.





관련 페이지

Categories:

Updated:

Leave a comment