Algorithm/Baekjoon(Java)

[백준/JAVA] 1157 : 단어 공부 ( System.in.read(); )

비망노트 2022. 7. 24. 15:56
문제

알파벳 대소문자로 된 단어가 주어지면, 이 단어에서 가장 많이 사용된 알파벳이 무엇인지 알아내는 프로그램을 작성하시오.

단, 대문자와 소문자를 구분하지 않는다.

입력

첫째 줄에 알파벳 대소문자로 이루어진 단어가 주어진다. 주어지는 단어의 길이는 1,000,000을 넘지 않는다.

 

출력

첫째 줄에 이 단어에서 가장 많이 사용된 알파벳을 대문자로 출력한다.

단, 가장 많이 사용된 알파벳이 여러 개 존재하는 경우에는 ?를 출력한다.

 

예제 입력 예제 출력
Mississipi ?
zZa Z
z Z
baaa A

 

⭕ 풀이

import java.util.*;
import java.io.*;

public class Main{
    public static void main(String[] args)throws IOException{
        
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        char[] chArr = br.readLine().toUpperCase().toCharArray();
        // MISSISSIPI
        
        char[] alpha = new char[26];
        char a ='A';
        for(int i=0;i<alpha.length;i++){
            alpha[i]= a;
            a++;
        }
        // A B C D E F G ....
        
        int[] countArr = new int[26];
        for(int i=0;i<alpha.length;i++){
            for(int j=0;j<chArr.length;j++){
                if(chArr[j]==alpha[i]){
                    countArr[i]++;
                }
            }
        } // MISSISSIPI
        // 0 0 0 0 0 0 0 0 4 0 0 0 1 0 0 1 0 0 4 0 0 0 0 0 0 0 
        
        char max ;
        int maxIdx = 0;
        for(int i=1;i<countArr.length;i++){
            if(countArr[maxIdx]<countArr[i]){
                maxIdx = i; 
            }
        }
        max = alpha[maxIdx];
        
        Arrays.sort(countArr);
        if(countArr[countArr.length-1]==countArr[countArr.length-2]){
            System.out.print("?");
        }else{
            System.out.print(max);
        }
    }
}

✅ 대문자 알파벳을 담은배열과, 입력받은 문자열을 char배열로 바꾸어

비교하며 해당알파벳의 인덱스를 count할 배열까지 만들어 작성했다.

작성하면서도 스스로 이배열이 이배열인가 헷갈리면서 작성했다.

그렇다 가독성도, 효율도 좋지못한 코드이다.

 

 

 

✅ 다른분의 코드

import java.io.IOException;
 
public class Main {
    public static void main(String[] args) throws IOException {
 
        int[] arr = new int[26];
 
        int c = System.in.read();
 
        while (c > 64) {	// 공백을 입력받는 순간 종료됨 
			
            if (c < 91) {
                arr[c - 65]++;
            } else {
                arr[c - 97]++;
            }
                c = System.in.read();
        }
 
 
        int max = -1;
        int ch = -2;	// ? 는 63 이다.
 
        for (int i = 0; i < 26; i++) {
 
            if (arr[i] > max) {
                max = arr[i];
                ch = i;
            } else if (arr[i] == max) {
                ch = -2;
            }
        }
        System.out.print((char) (ch+65));
    }
}

✅ 해석해보자

1. System.in.read(); 로 입력문자열에서 한문자씩 정수로 받는다.

 

2. 대문자 A~Z는 65~90  소문자 a~z는 97~122이므로 while의 조건문에 64보다 크다면 계속 반복하도록 설정한다.

 

3. if문으로 c가 91보다 작을경우 즉 대문자일경우 arr 배열에서 c-65 인덱스를 ++ 한다
   예를들면 대문자C가 입력되었다면 67인데 -65를 하여 arr[2]의 위치를 ++한다는 것이다. 

 

4. if문으로 else 즉 소문자일경우 97을 뺀위치를 ++한다.
    예를들어 소문자 c가 입력된다면 99인데 -97을해  arr[2]의 위치를 ++ 한다.

 3번과 4번 C와 c 대소문자의 차이는 있지만 if문을 거쳐 둘다 arr[2]번째위치를 증가시켰다.

 

5. 이후  while문이 끝나기전에 다시 System.in.read()로 c를 재할당시키고 while문의 처음으로 돌아간다.

 

-- 여기까지의 arr 배열은 0 0 0 0 0 0 0 0 4 0 0 0 1 0 0 1 0 0 4 0 0 0 0 0 0 0  이런식으로 만들어진다.

 

max와 ch 를 초기화시켜준 뒤

6. if문에서 arr[i]와 max 즉 -1을 비교해 0인덱스일 A 가 카운트된적이 없다해도 첫반복에서 max=0 ch=0으로 만들어준다.

 

7. 이후 arr[i]와 계속 비교하며 arr[i]가 max보다 클경우 계속 갱신해준다.

 

   만약 abczzz라는 문자열이 있었다한들 1 1 1 0 0 0 0 0 0 0.. 3 이렇게 생겼을텐데

  z까지 가기 전까지는 a,b,c 모두 1로 같으니까 ch는 -2를 유지하고 있다가 z까지갔을때 if조건을 만족하므로 

   max값과 ch값이 재할당된다.

   난 이부분에서 값이 같을경우 중복! 하고 break를 한다고 생각해서 정렬을 해야하나 싶어서 오히려 뒤죽박죽 만든것같다.

 

8. 마지막에 arr배열에서 가장 큰 값이아닌  '큰값의 인덱스'를 담았던ch값에서 +65 를하여

    (char)로 대문자로 만들어준다.

    abc라는 문자일경우 ch값이 -2 인채로 끝까지 진행되었을것이므로 

    -2 +65 인셈으로 아스키코드 63이 가리키는 ? 물음표가 된다.