[Java] 백준 : 1316번 : 그룹 단어 체커
https://www.acmicpc.net/problem/1316
접근 방법
1) 단어 개수 정수 N개 입력 받기
2) 조건문에 따라 그룹 단어 판단
3) 조건문 -> if - else 중첩
- charAt(j) != charAt(j+1) 방법으로 한글자씩 비교
- 한계 : aaba 처럼 문자열 길이가 랜덤이기에 이미 나왔던 연속돼서 나온 알파벳을 판단하기 어려웠다.
- 이전 문자와 현재 문자를 모두 기억하는 변수를 떠올리기 어려웠다.
import java.io.*;
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));
int N = Integer.parseInt(br.readLine());
int count =0;
for(int i=0; i<N; i++) {
String input = br.readLine();
for(int j=0; j<input.length()-1; j++) {
if(input.charAt(j) != input.charAt(j+1)) { // 모든 문자가 다를 경우
count++;
}
else if(input.charAt(j) == input.charAt(j+1)) { // 같은 문자가 연속해서 나올 경우
count++;
}
}
}
bw.write(String.valueOf(count));
br.close();
bw.flush();
bw.close();
}
}
크로아티아 알파벳 문제처럼 여러 조건문을 중첩해서 푸는 문제 였는줄 알았는데
이미 나왔던 문자가 나왔을 때를 판단하기 헷갈려서 고민하다가 다른 방법을 찾아봤다.
찾은 방법은
정답 코드
참고한 블로그 : https://st-lab.tistory.com/69
import java.io.*;
public class Main{
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException{
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int N = Integer.parseInt(br.readLine());
int count =0;
for(int i=0; i<N; i++) {
if(check() == true) {
count++;
}
}
bw.write(String.valueOf(count));
br.close();
bw.flush();
bw.close();
}
public static boolean check() throws IOException { // 그룹 단어를 체크할 함수
boolean[] check = new boolean[26]; // 그룹 단어를 판단하기 위한 boolean 배열 생성
int prev = 0;
String str = br.readLine();
for(int i=0; i<str.length(); i++) {
int now = str.charAt(i); // 현재 문자를 저장하는 변수
if(prev != now) { // 새로운 문자가 나온 경우 : (이전 문자 != 현재 문자)
if(check[now -'a'] == false) { // 이전에 등장한 적 없는지 확인(now-'a' 알파벳 인덱스로 변환)
check[now -'a'] = true; // 이전에 등장하지 않았으므로 check 배열에 'true' 표시
prev = now; // 이전 문자 = 현재 문자 대입 후 다음 반복문 실행
}
else { // 이미 나온 문자일 경우 -> 그룹 단어가 아님
return false; // 거짓 반환 (종료)
}
}
// 연속된 문자일 경우 (이전 문자 == 현재 문장)
else
continue;
}
return true;
}
}
- 한계 1) aaba 처럼 문자열 길이가 랜덤이기에 이미 나왔던 연속돼서 나온 알파벳을 판단하기 어려웠다.
해결 방법 : boolean 배열을 알파벳 개수 만큼 만들어서 그룹 단어를 판단한다.
- 한계 2) 이전 문자와 현재 문자를 모두 기억하는 변수를 떠올리기 어려웠다.
해결 방법 :변수를 여러개 선언하는 것이 아니라, prev(이전 문자)와 now(현재 문자) 두 변수를 만들어서
새로운 문자가 나오고 이전에 등장하지 않은 문자일 경우에만, prev = now로 변수를 변경해줘서 혼란이 없도록 한다.
boolean 배열
boolean[] check = new boolean[26];
true or false로 초기화 가능하다.
boolean[] check = {true, false};
기본값은 false이기에 check 배열은 false로 초기화
check[now-'a']
for(int i=0; i<str.length(); i++) {
int now = str.charAt(i); // 현재 문자를 저장하는 변수
if(prev != now) { // 새로운 문자가 나온 경우 : (이전 문자 != 현재 문자)
if(check[now -'a'] == false) { // 이전에 등장한 적 없는지 확인(now-'a' 알파벳 인덱스로 변환)
check[now -'a'] = true; // 이전에 등장하지 않았으므로 check 배열에 'true' 표시
prev = now; // 이전 문자 = 현재 문자 대입 후 다음 반복문 실행
}
else { // 이미 나온 문자일 경우 -> 그룹 단어가 아님
return false; // 거짓 반환 (종료)
}
}
// 연속된 문자일 경우 (이전 문자 == 현재 문장)
else
continue;
}
return true;
}
이전에 등장한 문자를 판단하기 위해 boolean 배열 [now-'a'] 방법을 사용한다.
사용하는 이유는 영어 알파벳을 배열의 인덱스로 사용하기 위함이다.
보통 영어 알파벳은 ASCII 코드에 따라 숫자로 매핑된다.
booelan check배열의 인덱스를 영어 알파벳에 해당하는 숫자로 매핑하기 위해 'a'(ASCII : 97) 를 빼준다.
check 배열은 모두 false로 초기화된 상태
input = aba
check ['a' - 'a'] = check[0] = false => 이전에 나온적X 알파벳 => check[0] = true
check['b' - 'a'] = check[1] = false => 이전에 나온적X 알파벳 => check[1] = true
check['a' - 'a'] = check[2] = false => a가 이미 나왔던 문자로 판단 => 그룹 단어X => false 반환 => 종료
문자를 숫자로 매핑하여 컴퓨터가 쉽게 처리하기 위해 아스키 코드를 사용한다.
게다가 알파벳 'a' ~ 'z' 아스키 코드 값은 연속적이고, 각 알파벳에 a를 뺄 경우 0~25까지 연속된 정수 값으로 매핑할 수 있기에 알파벳을 인덱스로 사용하는 배열을 구현한 것이다.