[데알] 백준 알고리즘 No. 1316 그룹 단어 체커(Java)
■ 문제 링크
https://www.acmicpc.net/problem/1316
1316번: 그룹 단어 체커
그룹 단어란 단어에 존재하는 모든 문자에 대해서, 각 문자가 연속해서 나타나는 경우만을 말한다. 예를 들면, ccazzzzbb는 c, a, z, b가 모두 연속해서 나타나고, kin도 k, i, n이 연속해서 나타나기 때
www.acmicpc.net
■ 소스코드 (Java)
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
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 numOfWords = Integer.parseInt(br.readLine());
int cnt = 0;
String word="";
for (int i = 0; i < numOfWords; i++) {
word = br.readLine();
if (solution(word) == 0) {
cnt++;
}
}
br.close();
bw.write(cnt+"");
bw.flush();
bw.close();
}
public static int solution(String word) {
// key = 알파벳, value = 필터링 된 단어에서 반복된 알파벳있는지 제확인할 숫자
Map<String, Integer> hashMap = new HashMap<>();
// 반복된 알파벳의 개수를 담을 변수
int result = 0;
// 입력된 단어에서 연속된 알파벳이 있다면 i번째 알파벳과 i+1번째 알파벳 중 i+1번째 알파벳을 공백으로 치환..(replaceFirst사용)
for (int i = 0; i < word.length() - 1; i++) {
if (word.charAt(i) == word.charAt(i + 1)) {
word = word.replaceFirst(Character.toString(word.charAt(i+1)), " ");
}
}
// 필터링
for (int i = 0; i < word.length(); i++) {
String character = Character.toString(word.charAt(i));
if(!character.equals(" ")) {
hashMap.put(character, hashMap.getOrDefault(character, 0) + 1);
}
}
Iterator<String> keys = hashMap.keySet().iterator();
while (keys.hasNext()) {
String key = keys.next();
// value중에 1이 넘는 value가 있다면 result에 1증가 : 반복된 알파벳의 수
if (hashMap.get(key) > 1) {
result += 1;
}
}
return result;
}
}
■ 풀이
메서드는 main메서드와 solution 메서드로 나뉜다.
▶ main 메서드
먼저 반복해서 입력할 단어의 수를 BufferedReader 인스턴스를 사용해서 입력을 한다.
br.readLine()는 문자열을 받기 때문에 Interger.parseInt()를 사용해서 int타입으로 형변환하고 몇 개의 단어가 입력될지 알려주는 numOfWords에 저장한다. int타입 cnt는 최종 결과값 출력을 위한 변수로 0으로 초기화해놓았다.
numOfWords 만큼 반복하는 for loop을 생성하고 if 조건에서 solution메서드의 인자로 입력받아서 저장해둔 word를 던져준다.
▶ solution(String word) 메서드
solution에서는 과연 무엇을 리턴하는지...??
먼저, 첫번째 반복문으로 각 문자마다 바로 뒤의 문자와 비교해 일치하면 해당하는 바로 뒤의 문자를 공백으로 치환해주는 단계를 거치고 중복 문자를 없앤 word를 얻는다.
replace / replaceAll → NOPE
replaceFirst → OK!
replace를 사용하게 되면 일치하는 모든 문자들을 치환해버린다. 문자 하나는 남겨야 하는데 다 공백 처리하면 우야노...???
(그래서 처음 반복된 문자만 치환할 replaceFirst를 사용했다.)
다음, 두번째 반복문으로 word의 길이만큼 반복하면서 위에서 치환된 공백일 경우 스킵하고 공백이 아닌 문자들만 hashMap에 키와 밸류로 저장해서 각 알파벳(key) 당 등장한 횟수(value)를 저장한다.
getOrDefault메서드를 사용해서 처음 저장되는 키와 값이면 키는 알파벳, 값은 defaultValue로 0을 저장하도록 했고, 이미 저장된 키가 있다면 해당 키로 얻어낸 값에 +1을 한 값을 저장하도록 했다. (엄청난 감동을 가져다 준 메서드.....ㅠ)
문제에서 제시한 조건을 만족하려면 중복을 제거한 단어의 알파벳 당 등장한 횟수는 모두 1이어야 한다. 2 이상인 경우 다른 알파벳을 건너뛴 후 다시 등장했다는 것을 의미....
마지막으로 Iterator를 사용해서 키와 값을 모두 체크한다. 혹시 2 이상인 value가 존재한다면 result에 1을 증가하도록 했다.
solution의 리턴 값 result를 가지고 돌아온 main메서드에서 0인 경우에만 매애앤 처음 선언한 cnt를 증가하도록 했다. 결국 cnt는 n번 입력받은 단어들이 문제에서 제시된 조건을 만족하면 개수를 카운트해주고 마지막에 cnt를 출력해주면 된다..
잘못된 점이나 보충할 부분이 있으면 코멘트 남겨주세요
작은 조언이 저에겐 성장의 원동력이 됩니다 :-)