휴대폰의 자판은 컴퓨터 키보드 자판과는 다르게 하나의 키에 여러 개의 문자가 할당될 수 있습니다. 키 하나에 여러 문자가 할당된 경우, 동일한 키를 연속해서 빠르게 누르면 할당된 순서대로 문자가 바뀝니다.
같은 규칙을 적용해 아무렇게나 만든 휴대폰 자판이 있습니다. 이 휴대폰 자판은 키의 개수가 1개부터 최대 100개까지 있을 수 있으며, 특정 키를 눌렀을 때 입력되는 문자들도 무작위로 배열되어 있습니다. 또, 같은 문자가 자판 전체에 여러 번 할당된 경우도 있고, 키 하나에 같은 문자가 여러 번 할당된 경우도 있습니다. 심지어 아예 할당되지 않은 경우도 있습니다. 따라서 몇몇 문자열은 작성할 수 없을 수도 있습니다.
이 휴대폰 자판을 이용해 특정 문자열을 작성할 때, 키를 최소 몇 번 눌러야 그 문자열을 작성할 수 있는지 알아보고자 합니다.
1번 키부터 차례대로 할당된 문자들이 순서대로 담긴 문자열배열 keymap
과 입력하려는 문자열들이 담긴 문자열 배열 targets
가 주어질 때, 각 문자열을 작성하기 위해 키를 최소 몇 번씩 눌러야 하는지 순서대로 배열에 담아 return 하는 solution 함수를 완성해 주세요.
-1
을 저장합니다.keymap
의 길이 ≤ 100keymap
의 원소의 길이 ≤ 100keymap[i]
는 i + 1번 키를 눌렀을 때 순서대로 바뀌는 문자를 의미합니다.keymap[0]
= "ABACD" 인 경우 1번 키를 한 번 누르면 A, 두 번 누르면 B, 세 번 누르면 A 가 됩니다.keymap
의 원소의 길이는 서로 다를 수 있습니다.keymap
의 원소는 알파벳 대문자로만 이루어져 있습니다.targets
의 길이 ≤ 100targets
의 원소의 길이 ≤ 100targets
의 원소는 알파벳 대문자로만 이루어져 있습니다.function solution(keymap, targets) {
const keyCountMap = new Map();
const MAX_COUNT = 100;
const calculateKeyCount = (target) => {
let totalKeyCount = 0;
for (let i = 0; i < target.length; i++) {
const key = target[i];
if (keyCountMap.get(key)) {
totalKeyCount += keyCountMap.get(key);
continue;
}
let keyCount = MAX_COUNT;
for (const keyStr of keymap) {
const keyIndex = keyStr.indexOf(key);
if (keyIndex !== -1) {
keyCount = Math.min(keyCount, keyIndex + 1);;
}
}
if (keyCount === MAX_COUNT) {
return -1;
}
keyCountMap.set(key, keyCount);
totalKeyCount += keyCount;
}
return totalKeyCount;
};
return targets.map(target => calculateKeyCount(target));
}
book_time
이 매개변수로 주어질 때, 코니에게 필요한 최소 객실의 수를 return 하는 solution 함수를 완성해주세요.book_time
의 길이 ≤ 1,000book_time[i]
는 ["HH:MM", "HH:MM"]
의 형태로 이루어진 배열입니다"00:00"
부터 "23:59"
까지로 주어집니다.function solution(book_time) {
let finishedBookTimes = [];
const calculateTotalTime = (time) => {
const [hour, minute] = time.split(':').map(Number);
return hour * 60 + minute;
}
book_time.sort().forEach((bookTime) => {
const checkinTime = calculateTotalTime(bookTime[0]);
const checkoutTime = calculateTotalTime(bookTime[1]);
if (!finishedBookTimes.length) {
finishedBookTimes.push(checkoutTime + 10);
return;
}
finishedBookTimes.sort();
let isBookCountinuous = false;
for (let i = 0; i < finishedBookTimes.length; i++) {
if (checkinTime >= finishedBookTimes[i]) {
finishedBookTimes[i] = checkoutTime + 10;
isBookCountinuous = true;
break;
}
}
if (!isBookCountinuous) {
finishedBookTimes.push(checkoutTime + 10);
}
});
return finishedBookTimes.length;
}
1 x 1 크기의 칸들로 이루어진 직사각형 격자 형태의 미로에서 탈출하려고 합니다. 각 칸은 통로 또는 벽으로 구성되어 있으며, 벽으로 된 칸은 지나갈 수 없고 통로로 된 칸으로만 이동할 수 있습니다. 통로들 중 한 칸에는 미로를 빠져나가는 문이 있는데, 이 문은 레버를 당겨서만 열 수 있습니다. 레버 또한 통로들 중 한 칸에 있습니다. 따라서, 출발 지점에서 먼저 레버가 있는 칸으로 이동하여 레버를 당긴 후 미로를 빠져나가는 문이 있는 칸으로 이동하면 됩니다. 이때 아직 레버를 당기지 않았더라도 출구가 있는 칸을 지나갈 수 있습니다. 미로에서 한 칸을 이동하는데 1초가 걸린다고 할 때, 최대한 빠르게 미로를 빠져나가는데 걸리는 시간을 구하려 합니다.
미로를 나타낸 문자열 배열 maps
가 매개변수로 주어질 때, 미로를 탈출하는데 필요한 최소 시간을 return 하는 solution 함수를 완성해주세요. 만약, 탈출할 수 없다면 -1을 return 해주세요.
maps
의 길이 ≤ 100maps[i]
의 길이 ≤ 100maps[i]
는 다음 5개의 문자들로만 이루어져 있습니다.function solution(maps) {
const n = maps.length;
const m = maps[0].length;
const start = [];
const lever = [];
let startIndex = -1;
let leverIndex = -1;
// start-lever, lever-exit로 두번으로 나눠서 최단거리를 계산하기 위해 2개의 maze 배열을 만듬
const maze1 = maps.map((str, strIndex) => {
// start, lever 위치를 찾음
if (startIndex === -1) {
startIndex = str.indexOf('S');
if (startIndex !== -1) {
start[0] = strIndex;
start[1] = startIndex;
}
}
if (leverIndex === -1) {
leverIndex = str.indexOf('L');
if (leverIndex !== -1) {
lever[0] = strIndex;
lever[1] = leverIndex;
}
}
return str.split('');
});
const maze2 = maps.map(str => str.split(''));
const calculateTargetDistance = (start, arr, target) => {
const dx = [-1, 1, 0, 0];
const dy = [0, 0, -1, 1];
const queue = [start];
let time = 0;
// 시작위치 막기
arr[start[0]][start[1]] = 'X';
// 너비탐색(BFS)
while (queue.length) {
// q의 길이가 변하면 안되므로 변수에 저장함
let size = queue.length;
for (let i = 0; i < size; i++) {
const [x, y] = queue.shift();
// 상하좌우 탐색
for (let j = 0; j < dx.length; j++) {
let nx = x + dx[j];
let ny = y + dy[j];
// 좌표 값 범위에 있으면서 벽(X)이 아닐 때
if (nx >= 0 && nx < n && ny >= 0 && ny < m && arr[nx][ny] !== 'X') {
// target과 만나면 걸린 시간을 반환함
if (arr[nx][ny] === target) {
return time + 1;
}
// 현재 좌표를 queue에 넣고 다시 갈 수 없게 벽(X)으로 막음
queue.push([nx, ny]);
arr[nx][ny] = 'X';
}
}
}
// 한 사이클이 끝나면 1초 증가
time++;
}
// target을 못 만나면 0 반환
return 0;
};
const distanceToLever = calculateTargetDistance(start, maze1, 'L');
// lever을 못 만나면 -1 반환
if (!distanceToLever) {
return -1;
}
const distanceToExit = calculateTargetDistance(lever, maze2,'E');
// exit을 못 만나면 -1 반환
if (!distanceToExit) {
return -1;
}
// start-lever과 lever-exit 최단거리의 합을 반환함
return distanceToLever + distanceToExit;
}