function solution(keymap, targets) {
let result = [];
let trie = new Trie();
// keymap으로 Trie 생성
for(key of keymap){
trie.addWord(key);
}
// targets에 적힌 각각의 문자열에 대해 결과를 판별
for(let target of targets){
// 각 문자열을 구성할 때, 키보드가 눌린 횟수
let pushCount = 0;
for(let char of target){
const level = trie.BFS(char);
// level이 -1이라면 문자열을 구성할 수 없다는 뜻이므로
// result에 -1이 들어갈 수 있도록 처리한다.
if(level === -1){
pushCount = -1;
break;
}
pushCount += level;
}
result.push(pushCount);
}
return result;
}
class Node{
constructor(){
this.children = {};
this.isEndOfWord = false;
}
}
class Trie{
constructor(){
this.root = new Node();
}
addWord(word){
let current = this.root;
for(let char of word){
if(!current.children[char]){
current.children[char] = new Node();
}
current = current.children[char];
}
current.isEndOfWord = true;
}
BFS(str){
let queue = [];
let node = this.root;
let levelCount = 0;
queue.push(node);
while(queue.length > 0){
const sameLevelLength = queue.length;
let found = false;
for(let i = 0; i < sameLevelLength; i++){
node = queue.shift();
// node의 자식 중 str이 있으면, 그 자식 노드가 최소 level을 가진다.
if(node.children[str]){
found = true;
break;
}
// 현재 node가 자식으로 가지고 있는 모든 노드를 queue에 넣는다.
for(let child in node.children){
queue.push(node.children[child]);
}
}
if(found){
return ++levelCount;
}
// 순회를 모두 마쳤음에도 일치하는 키를 찾지 못했으며
// 더이상 순회할 키가 없는 경우에는 문자열을 생성할 수 없다고 판단
if(queue.length === 0){
return -1;
}
// 다음 level로 들어감을 의미
levelCount++;
}
return -1;
}
}
이 문제는 문자열을 다루는 문제이고, 키가 눌릴 때마다 다음 문자열이 나온다는 점에서 Trie
구조가 생각났다.
최소한의 횟수로 문자열을 완성하기 위해서는 몇 번 눌렀는지를 아는 것이 중요했고,
이는 Trie
에서 level
을 활용하는 것으로 구현할 수 있겠다고 판단했다.
따라서, Trie
를 구성하는 것은 keymap
을 사용하는 것으로 결정했다.
targets
으로 주어진 문자열들을 만들기 위해 필요한 최소한의 키 입력 횟수를 구하는 것이기 때문에,
Trie
에 대하여 BFS
를 진행하면, 특정 문자열을 입력할 수 있는 최소한의 키 입력 횟수를 얻을 수 있다.
따라서, targets
로 주어진 문자열들의 각 문자에 대해 한번씩 BFS
를 진행한다.
Trie
는 루트 노드가 값을 가지고 있는 것이 아니기 때문에, 바로 children
을 탐색하는 것으로 진행해도 된다.
자식 노드 중에 키로 입력할 수 있는 것이 있다면, 그 때가 가장 낮은 level
이므로,
그 level + 1
(루트가 level 0
라고 가정했기 때문)을 반환한다.
만약, 모든 노드를 순회했음에도 아무 결과를 얻지 못했다면 더 이상 진행할 수 없는 문자열이므로 -1
을 반환한다.
자판을 대충 만들지 마세요