문제 : 프로그래머스 Level 4 (카카오 기출문제)
구현(코드)
import java.util.HashMap;
import java.util.Map;
class Solution {
public class Node {
Map<Character, Node> child = new HashMap<>(); // 특정 문자의 자식 노드들을 저장하는 HashMap
Node before = null; // 부모 계층 노드
Boolean isEnd = false; // leaf 노드인지 확인
}
public class Trie { // Trie 구조를 갖는 클래스
public Node root = new Node(); // 루트 노드
/*
insert : 주어진 문자열을 Trie에 삽입하는 메서드
--> 문자열의 각 글자를 Trie에 추가하면서 해당 노드의 자식 노드 맵에 추가
*/
public void insert(String input) {
Node node = this.root; // 빈 기준 노드를 가져와서 첫번째 계층 노드로 설정
for (int i = 0; i < input.length(); i++) {
Node before = node; // i-1번째에 노드로 만들어준 문자를 before에 저장
node = node.child // i-1번째 노드의 자식들중에
.computeIfAbsent(input.charAt(i) // i번째 글자가 없으면
, k -> new Node()); // 해당 문자로 새로운 노드를 만들어 child에 넣어준다
/*
Map.computeIfAbsent(lamda) : 특정 키에 해당하는 값이 존재하는지 확인한 후, 없으면 새로 만들어서 넣어주는 메서드
*/
node.before = before; // i-1번째 노드를 해당 글자 노드의 부모 노드로 설정
}
node.isEnd = true; // 반복문이 끝나면 문자열 전체 검사 완료 --> leaf 노드 표시
}
/*
calInputCnt : 설계된 트라이를 바탕으로 입력받은 단어를 완성시키기 위해 필요한 최소 글자수를 구하는 메서드
*/
public int calInputCnt(String input) {
Node node = this.root;
//마지막 노드로 이동
for (int i = 0; i < input.length(); i++) { // 한글자씩 검사하면서
node = node.child // 노드의 자식들중에
.getOrDefault(input.charAt(i), null); // i 번째 글자가 있으면 해당 노드를 반환하고 없으면 null 반환 --> 자식으로 타고 들어감
}
//1. 마지막 노드가 leaf 노드가 아닐 경우 <-> Trie에 반영된 단어가 아닐경우
if (node.child.size() != 0)
return input.length(); // 전체를 다 작성해야 검색 가능
//2. 마지막 노드가 leaf 노드일 경우 <-> Trie에 반영된 단어를 검색한 경우
int reduce = 0; // 생략 가능한 검색 횟수
while(true) { // 부모 노드들을 따라가면서 최소 입력 횟수를 계산
node = node.before; // 해당 노드의 부모노드를 참조해 올라가면서
if (node == null) { // 부모노드가 없으면
reduce--; // 다시 아래로 내려가주고 (해당 글자는 직접 검색 횟수에 포함시켜야함)
break; // 반복문 종료
}
if (node.isEnd == false && node.child.size() == 1)
// 부모노드가 리프노드가 아닌데 자식 노드가 하나, 즉 현재 검사하는 나밖에 없을 때
reduce++; // 검색 횟수를 1회 빼준다
else
break;
}
return input.length() - reduce; // 전체 문자 갯수에서 생략가능한 검색횟수를 빼준 값을 리턴
} // calInputCnt
} // Trie
public int solution(String[] words) {
Trie trie = new Trie();
//트라이 설계 (모든 단어들을 Trie 자료구조에 반영)
for (int i = 0; i < words.length; i++)
trie.insert(words[i]);
//각 단어의 최소 입력 횟수 계산
int result = 0;
for (int i = 0; i < words.length; i++) {
result += trie.calInputCnt(words[i]); // 누적
}
return result;
}
}
댓글남기기