[백준] 1157번 : 단어 공부 - Java(자바)

이정우·2021년 9월 3일
0

백준

목록 보기
9/32

이번 문제는 알파벳 문자열을 입력 받아 가장 많이 사용된 알파벳을 찾는 프로그램이었습니다. 특이사항으로는 입력된 알파벳 문자열에서는 대소문자를 구별하지 않고 카운팅하고, 가장 많이 쓰인 알파벳을 출력할 때는 대문자로만 출력됩니다. 또한 가장 많이 사용된 횟수가 같은 알파벳이 2개 이상 존재하면 ?을 출력해야 했습니다.

import java.util.Scanner;

public class Study_word_1157 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		String word = sc.next(); // 알파벳 입력 받기
		word = word.toLowerCase(); // 모든 알파벳 소문자로 통일
		int[] Counter = new int[26]; // 알파벳 개수만큼 배열 생성
		int count = 0; // 알파벳 사용 횟수 카운팅 할 count 변수 값 0으로 초기화
		for (int i = 0; i < 26; i++) { // a - z까지 총 26번 반복.
			for (int k = 0; k < word.length(); k++) { // 입력받은 문자 길이만큼 반복
				if (word.charAt(k) == (i + 97)) { // i(현재 찾고 있는 알파벳)가 입력한 문자열에 존재하면 count++해줌
					count++;
				}
			}
			Counter[i] = count; // count값을 각 배열에 저장 후
			count = 0; // 다시 0으로 초기화.
		}
		int top = Counter[0]; //사용 횟수가 가장 큰 값 찾기 위해 저장.
		int most = 0; // 가장 많이 사용된 알파벳 찾기.
		for (int j = 0; j < 26; j++) { // 가장 많이 쓰인 알파벳 찾기.
			if (top < Counter[j]) {
				top = Counter[j];
				most = j;
			}
		}
		for (int g = 0; g < 26; g++) {
			if (g != most) {
				if (Counter[most] == Counter[g]) {
					System.out.println("?");
					System.exit(0);
				}
			}
		}
		System.out.println((char) (most + 65));
	}

}

이번 문제에서 저는 Scanner 클래스를 통해 알파벳 문자열을 입력받고 toLowerCase() 메서드를 이용해서 입력받은 문자열을 소문자로 바꿨습니다. 이렇게 소문자로 바꾼 이유는 알파벳 사용 횟수를 조사할 때 아스키코드를 편하게 이용하기 위해서였습니다. 그 다음에는 알파벳 개수 만큼의 Counter 배열을 생성해서 각 배열에다가 알파벳이 몇 번 사용되었는지 저장하였습니다.(배열 0번은 a, 1번은 b, 2번은 c....)

for (int i = 0; i < 26; i++) { // a - z까지 총 26번 반복.
			for (int k = 0; k < word.length(); k++) { // 입력받은 문자 길이만큼 반복
				if (word.charAt(k) == (i + 97)) { // i(현재 찾고 있는 알파벳)가 입력한 문자열에 존재하면 count++해줌
					count++;
				}
			}
			Counter[i] = count; // count값을 각 배열에 저장 후
			count = 0; // 다시 0으로 초기화.
		}

첫 반복문이자 중첩 반복문을 사용한 for문에서는 a - z의 개수만큼인 26번 반복문을 돌리고 중첩 반복문에서 문자의 길이만큼 반복문을 돌리면서 if문을 통해 해당 알파벳이 몇 번 쓰였는지 조사 후 count로 누적해주었습니다. if (word.charAt(k) == (i + 97)) 에서 +97을 한 이유는 아스키 코드 a(소문자)가 97이기에 97을 더해주었습니다. 그 후 변수 top과 most를 새로 선언해 저장된 Counter배열에서 가장 큰 값, 즉 가장 많이 사용된 알파벳 위치를 찾아냈습니다. 그다음 마지막으로 만약 가장 많이 사용된 횟수가 같은 알파벳이 2개이상 있으면 ?를 출력해주어야 하기 때문에

for (int g = 0; g < 26; g++) {
			if (g != most) {
				if (Counter[most] == Counter[g]) {
					System.out.println("?");
					System.exit(0);
				}
			}

for 문과 if문을 사용해서 가장 많이 사용된 횟수가 2개이상 존재한다면 ?를 출력 후 프로그램을 강제 종료 시켰습니다.

처음 문제를 봤을 때는 설명도 짧고 문제에서 원하는 바도 쉬워 보이고 대충 어떤 방식으로 풀어야 할지 보이는거 같아서 쉽겠지 했는데 생각보다 어려웠고 생각할게 많았던 문제였습니다. 괜히 정답률이 30%대가 아닌거 같았습니다. 다른 분들의 코드를 봐보니 map을 사용한다던지 해서 데이터를 저장하는 경우도 배울 수 있었습니다. 특히 이번에 제가 크게 배운 점은 int배열을 처음 생성하게 되면 기본 값이 0으로 초기화 된다는 점을 제대로 생각하지 않았다는 것입니다. 저는 무턱대고 count등을 사용해서 횟수를 늘려줬는데 그냥 단순하게 배열을 생성 후 Counter[0]++;를 해주면 해당 배열의 값이 증가되는것을 알 수 있었습니다. 이 문제때문에 한 30분동안 고민하면서 배열마다 객체를 new로 생성해줘서 변수를 관리해줘야 하나? 어떻게 해야 하나? 고민 많이 했는데 쉬운 방법을 배울 수 있었던거 같습니다.

횟수를 카운팅 하는 count 변수 삭제 버전

import java.util.Scanner;

public class new_1157 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		String word = sc.next(); // 알파벳 입력 받기
		word = word.toLowerCase(); // 모든 알파벳 소문자로 통일
		int[] Counter = new int[26]; // 알파벳 개수만큼 배열 생성
		for (int i = 0; i < 26; i++) { // a - z까지 총 26번 반복.
			for (int k = 0; k < word.length(); k++) { // 입력받은 문자 길이만큼 반복
				if (word.charAt(k) == (i + 97)) { // i(현재 찾고 있는 알파벳)가 입력한 문자열에 존재하면 Counter객체 ++해줌
					Counter[i]++;
				}
			}
		}
		int top = Counter[0];
		int most = 0; // 가장 많이 사용된 알파벳 찾기.
		for (int j = 0; j < 26; j++) { // 가장 많이 쓰인 알파벳 찾기.
			if (top < Counter[j]) {
				top = Counter[j];
				most = j;
			}
		}
		for (int g = 0; g < 26; g++) {
			if (g != most) {
				if (Counter[most] == Counter[g]) {
					System.out.println("?");
					System.exit(0);
				}
			}
		}
		System.out.println((char) (most + 65));
	}

}

int count를 삭제하고 첫 for문의 중첩 for문 안의 if문을 보시면 Counter[i]++;를 한걸 볼 수 있습니다. 즉 배열 초기화시 0으로 값이 초기화 되는걸 이용해서 풀어봤습니다.

출처 : 백준 1157번 https://www.acmicpc.net/problem/1157

profile
프로그래밍 공부 중!

0개의 댓글