[★3][백준1157번]단어 공부 (JAVA)

Date:     Updated:

카테고리:

태그:

[★3][백준1157번]단어 공부 (JAVA)

1157번 문제 ☞ https://www.acmicpc.net/problem/1157

난이도 ☞ [★3]

단어 공부

  • 문제
    • 알파벳 대소문자로 된 단어가 주어지면, 이 단어에서 가장 많이 사용된 알파벳이 무엇인지 알아내는 프로그램을 작성하시오. 단, 대문자와 소문자를 구분하지 않는다.
    • 첫째 줄에 알파벳 대소문자로 이루어진 단어가 주어진다. 주어지는 단어의 길이는 1,000,000을 넘지 않는다.
    • 첫째 줄에 이 단어에서 가장 많이 사용된 알파벳을 대문자로 출력한다. 단, 가장 많이 사용된 알파벳이 여러 개 존재하는 경우에는 ?를 출력한다.

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

내가 푼 풀이

이번 문제는 입력에서의 대소문자의 구분이 없으며, 출력은 대문자로 하되 가장 많이 받은 문자가 2개 이상일 경우에는 ‘?’를 출력하고 그렇지 않을 경우 가장 많은 문자를 대문자로 출력하는 문제이다. 이걸 어떻게 풀까 생각하다가 for문과 if를 조합하고 아스키코드에 대입해서 푸는게 좋아보여서 아스키코드로 대입하여 풀어보았다.

[ 풀이 1 ]

메모리 : 28928 KB
시간 : 468 ms

Scanner

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);

		int[] arr = new int[26]; // 영문자의 갯수
		String str = s.next();

		for (int i = 0; i < str.length(); i++) {
			// 대문자를 받았을 경우 아스키코드 값에서 대문자의 범위
			if (65 <= str.charAt(i) && str.charAt(i) <= 90) {
				arr[str.charAt(i) - 65]++; // 65는 대문자 'A'로 대체 가능
			}
			// 소문자를 받았을 경우 아스키코드 값에서 소문자의 범위
			else {
				arr[str.charAt(i) - 97]++; // 97은 소문자 'a'로 대체 가능
			}
		}

		int max = 0;
		char ch = 'a';

		for (int i = 0; i < 26; i++) {
			if (arr[i] > max) {
				max = arr[i];
				// 대문자로 출력해야하기 때문에 65를 더해줌
				ch = (char) (i + 65);
			} else if (arr[i] == max) {
				ch = '?';
			}
		}
		System.out.println(ch);
	}
}

이렇게 코드를 한번에 작성해놓고 풀이를 하려고하니 너무 복잡한 거 같아 한 구절씩 떼어서 설명을 해보겠습니다.

int[] arr = new int[26]; // 영문자의 갯수
String str = s.next();

먼저, 문자의 빈도수를 나타내기 위한 배열을 하나 선언하고 문자열 str을 입력 받는다.

for (int i = 0; i < str.length(); i++) {}

문자열 str을 처음부터 끝까지 검사하기 위해 반복문을 작성을 합니다. 물론, 문자열의 길이만큼이기 때문에 .length()만큼 합니다.

for (int i = 0; i < str.length(); i++) {
	if (65 <= str.charAt(i) && str.charAt(i) <= 90) {
		arr[str.charAt(i) - 65]++;
	}
	else {
		arr[str.charAt(i) - 97]++; 
	}
}

아스키코드표를 보게 되면, 대문자의 A-Z65~90까지의 범위입니다. 그리고 소문자 a-z97~122까지입니다. 그래서 각각 조건문에 따라 -65 혹은 -97을 해준 것이다. 그렇게 입력 받은 값에 대해 각각 빼주고 나면 arr[] 인덱스가 있을텐데 그 값을 ++;으로 증가시켜준다. 여기까지 문자 검사를 끝을 마치게 된다.
그렇게 문자 검사를 끝내고나면 배열 원소 값을 비교하여 가장 큰 값을 가지고 있는 배열 인덱스 문자를 출력을 해야한다. 그렇게 하기위해서 최댓값을 저장할 변수를 선언을 해주고, 출력할 변수를 선언을 해주어야한다.

int max = 0;
char ch = 'a';

그리고 난 후 배열 값을 확인하기 위해 반복문을 작성하여 확인해준다.

int max = 0;
char ch = 'a';

for (int i = 0; i < 26; i++) {}

배열 원소 값이 int max보다 클 경우, 해당 원소 값으로 대체되게 해주고, char ch로 해당 인덱스에 대응하는 문자로 대체해준다.

int max = 0;
char ch = 'a';

for (int i = 0; i < 26; i++) {
	if (arr[i] > max) {
		max = arr[i];
		// 대문자로 출력해야하기 때문에 65를 더해줌
		ch = (char) (i + 65);
	} else if (arr[i] == max) {
		ch = '?';
	}
}

이렇게 짜여진 코드들을 다 조합하여 출력하면 풀이에 있는 코드가 된다. 위쪽에도 있지만 풀이를 보기 전과 후의 비교를 위해 아래에도 한번 더 작성해두겠습니다.

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);

		int[] arr = new int[26]; // 영문자의 갯수
		String str = s.next();

		for (int i = 0; i < str.length(); i++) {
			// 대문자를 받았을 경우 아스키코드 값에서 대문자의 범위
			if (65 <= str.charAt(i) && str.charAt(i) <= 90) {
				arr[str.charAt(i) - 65]++; // 65는 대문자 'A'로 대체 가능
			}
			// 소문자를 받았을 경우 아스키코드 값에서 소문자의 범위
			else {
				arr[str.charAt(i) - 97]++; // 97은 소문자 'a'로 대체 가능
			}
		}

		int max = 0;
		char ch = 'a';

		for (int i = 0; i < 26; i++) {
			if (arr[i] > max) {
				max = arr[i];
				// 대문자로 출력해야하기 때문에 65를 더해줌
				ch = (char) (i + 65);
			} else if (arr[i] == max) {
				ch = '?';
			}
		}
		System.out.println(ch);
	}
}

Scanner외의 System.in.read()으로도 풀이를 할 수 있으며, 한번 코드를 작성해보도록 하겠습니다.

[ 풀이 2 ]

메모리 : 14184 KB
시간 : 156 ms

System.in.read()

import java.io.IOException;

public class Main {
	public static void main(String[] args) throws IOException {
		 
		int[] arr = new int[26]; 
		int read = System.in.read();
 
		while (read > 64) {	// 엔터를 누르면 종료됨		
			if (read < 91) {
				arr[read - 65]++;
			} else {
				arr[read - 97]++;
			}
			read = System.in.read();
		}
 
		int max = 0;
		int ch = 'a';
 
		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));
	}
 
}

아스키코드표에서 ?63이다. 그걸 주의한다면 별 문제없이 코드 해독이 되었을 것이라고 생각이 됩니다. 성능면에서 월등히 System.in.read()가 우수함을 보여주고 있습니다.
그리고 이번 문제를 계기로 Scanner를 선언할 때, Scanner s = new Scanner();가 아닌 Scanner in = new Scanner()로 해야겠다라는 생각이 들었다. 변수 s로 하다보니까 불편한 점이 조금씩 보이기 시작했다.

BKJN 카테고리 내 다른 글 보러가기

댓글 남기기