알고리즘
[Javascript] 프로그래머스 - 지게차와 크레인
J3SUNG
2025. 2. 23. 18:28
728x90
문제 설명
물류창고에는 알파벳 대문자로 구분되는 컨테이너들이 n×m 크기의 격자로 배치되어 있다. 출고 요청이 들어올 때, 요청된 컨테이너를 창고에서 꺼내야 한다.
- 지게차를 사용하면 창고 외부와 연결된 동일 종류의 컨테이너만 출고된다.
- 크레인을 사용하면 해당 종류의 모든 컨테이너를 출고할 수 있다.
모든 요청을 수행한 후 남아있는 컨테이너의 개수를 구하는 문제이다.
제한 사항
- 2 ≤ n, m ≤ 50
- storage는 알파벳 대문자로 구성된 2차원 배열
- requests의 길이는 1 이상 100 이하
- requests[i]는 한 종류의 알파벳 대문자로 이루어진 문자열(길이 1이면 지게차, 길이 2이면 크레인)
해결 방법
알고리즘: BFS, 구현
- 창고 확장 및 경계 설정
- n+2 × m+2 크기의 새로운 배열을 생성하여 외부 경계를 -1로 설정한다.
- 기존 데이터를 중앙에 배치해 경계를 손쉽게 판단할 수 있도록 한다.
- 창고 외부 영역 식별 (BFS 탐색)
- 외부 공기와 연결된 빈 공간을 BFS로 탐색하면서 -1로 표시한다.
- 지게차 출고 시, 외부와 연결된 컨테이너 판별을 쉽게 하기 위함이다.
- 출고 요청 처리
- 요청이 길이 1이면 지게차를 사용해 외부와 인접한 컨테이너만 제거한다.
- 요청이 길이 2이면 크레인을 사용해 해당 종류의 컨테이너를 모두 제거한다.
- 출고 이후 다시 BFS를 수행하여 외부와 연결된 공간을 갱신한다.
- 남은 컨테이너 개수 계산
- BFS 완료 후 남아있는 컨테이너 개수를 세어 반환한다.
시간 복잡도
- updateExternal(): BFS 탐색 O(nm)
- 각 요청 처리 시 O(nm)
- 최대 요청 개수 100개이므로 최악의 경우 O(100 × nm) = O(5000 × 50) ≈ 250,000
구현 코드
function solution(storage, requests) {
const n = storage.length,
m = storage[0].length;
const grid = Array.from({ length: n + 2 }, (_, i) =>
Array.from({ length: m + 2 }, (_, j) =>
i === 0 || j === 0 || i === n + 1 || j === m + 1 ? -1 : storage[i - 1][j - 1]
)
);
const moves = [
[0, 1],
[1, 0],
[0, -1],
[-1, 0],
];
function updateExternal() {
const rows = grid.length,
cols = grid[0].length;
const visited = Array.from({ length: rows }, () => Array(cols).fill(false));
const queue = [[0, 0]];
visited[0][0] = true;
while (queue.length) {
const [y, x] = queue.shift();
for (const [dy, dx] of moves) {
const ny = y + dy,
nx = x + dx;
if (ny < 0 || nx < 0 || ny >= rows || nx >= cols || visited[ny][nx]) continue;
if (typeof grid[ny][nx] === "number") {
grid[ny][nx] = -1;
visited[ny][nx] = true;
queue.push([ny, nx]);
}
}
}
}
for (let idx = 0; idx < requests.length; idx++) {
const req = requests[idx];
const target = req[0];
if (req.length === 1) {
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= m; j++) {
if (grid[i][j] !== target) continue;
for (const [dy, dx] of moves) {
if (grid[i + dy][j + dx] === -1) {
grid[i][j] = idx;
break;
}
}
}
}
} else {
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= m; j++) {
if (grid[i][j] === target) grid[i][j] = Infinity;
}
}
}
updateExternal();
}
let answer = 0;
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= m; j++) {
if (typeof grid[i][j] === "string") answer++;
}
}
return answer;
}