문제
You are given an m x n grid where each cell can have one of three values:
- 0 representing an empty cell,
- 1 representing a fresh orange, or
- 2 representing a rotten orange.
Every minute, any fresh orange that is 4-directionally adjacent to a rotten orange becomes rotten.
Return the minimum number of minutes that must elapse until no cell has a fresh orange. If this is impossible, return -1.
예시
xample 1:
Input: grid = [[2,1,1],[1,1,0],[0,1,1]]
Output: 4
Example 2:
Input: grid = [[2,1,1],[0,1,1],[1,0,1]]
Output: -1
Explanation: The orange in the bottom left corner (row 2, column 0) is never rotten, because rotting only happens 4-directionally.
Example 3:
Input: grid = [[0,2]]
Output: 0
Explanation: Since there are already no fresh oranges at minute 0, the answer is just 0.
제약 조건
Constraints:
- m == grid.length
- n == grid[i].length
- 1 <= m, n <= 10
- grid[i][j] is 0, 1, or 2.
풀이 과정
그리드를 입력 받고 각 값에 0, 1, 또는 2를 할당한다.
1은 신선한 오렌지, 2는 썩은 오렌지, 0은 빈 공간이다.
과수원을 지날 때마다 썩은 오렌지에 수평 또는 수직으로 인접한 모든 오렌지도 썩게 된다. 신선한 오렌지가 남지 않을 때까지 경과된 최소 시간(분)을 반환해야 한다.
예시 )
[0, 0]의 주황색은 손상되어 도착한다. 1분이 지나면 인접한 오렌지도 손상된다. 1분 더 지나면 상할 수 있는 모든 오렌지 가 상하게 된다.
* 참고 사항- 이 특정 예에서는 아직 신선한 오렌지가 남아 있기 때문에 실제로 -1을 반환한다. [2, 2]의 주황색이 없으면 2가 답이 된다.
- 호출 후, cycleOranges는 스톱워치를 증가시키면서 부패 주기를 통해 오렌지의 속도를 높인다.
- 이렇게 하면 모든 오렌지가 상할 수 있고 상하기 전에 몇 분이 경과했는지 알 수 있다.
- 그런 다음 (30행) 스톱워치가 실제로 시간을 기록했는지, 과수원이 '비어 있는지', 즉 존재하는 모든 오렌지가 상했다는 의미인지 확인한다.
- 스톱워치 시간에 관계없이 그리드에 여전히 신선한 오렌지가 있으면 -1이 반환된다.
해결 코드
/**
* @param {number[][]} grid
* @return {number}
*/
var orangesRotting = function(grid) {
if (emptyOrchard(grid)) {
return 0;
}
var stopwatch = 0;
var cycleOranges = (grid) => {
var checked = [];
for (var i = 0; i < grid.length; i++) {
for (var j = 0; j < grid[i].length; j++) {
if (grid[i][j] === 2 && !isDuplicate(checked, [i, j])) {
var adjacent = adjacencies(grid, i, j);
if (adjacent) {
adjacent.forEach(freshOrange => {
grid[freshOrange[0]][freshOrange[1]] = 2;
checked.push([freshOrange[0], freshOrange[1]]);
});
}
}
}
}
stopwatch++;
return adjacenciesRemain(grid) ? cycleOranges(grid) : null;
}
cycleOranges(grid);
return stopwatch > 0 && emptyOrchard(grid) ? stopwatch : -1;
};
// 신선한 오렌지 인접 관계에 상한 오렌지가 있는지 없는지 그리드를 점검
var adjacenciesRemain = (grid) => {
for (var i = 0; i < grid.length; i++) {
for (var j = 0; j < grid[i].length; j++) {
if (grid[i][j] === 2 && adjacencies(grid, i, j)) {
return true;
}
}
}
return false;
}
// 사용 가능한 모든 인접의 좌표를 확인
var adjacencies = (tree, i, j) => {
var adjacent = [];
var right = tree[i][j + 1];
var left = tree[i][j - 1];
var up = tree[i - 1] === undefined ? undefined : tree[i - 1][j];
var down = tree[i + 1] === undefined ? undefined : tree[i + 1][j];
right === 1 ? adjacent.push([i, j + 1]) : null;
up === 1 ? adjacent.push([i - 1, j]) : null;
left === 1 ? adjacent.push([i, j - 1]) : null;
down === 1 ? adjacent.push([i + 1, j]) : null;
return adjacent.length > 0 ? adjacent : false;
}
// 인자 어레이의 신뢰성 확인
var isDuplicate = (arr1, arr2) => {
for (var i = 0; i < arr1.length; i++) {
if (JSON.stringify(arr1[i]) === JSON.stringify(arr2)) {
return true;
}
}
return false;
}
// 모든 오렌지가 썩었거나 오렌지가 전혀 없는 상태를 체크
var emptyOrchard = (grid) => {
var rotten = false;
var fresh = false;
var absent = false;
for (var i = 0; i < grid.length; i++) {
for (var j = 0; j < grid[i].length; j++) {
if (grid[i][j] === 2) {
rotten = true;
} else if (grid[i][j] === 1) {
fresh = true;
} else if (grid[i][j] === 0) {
absent = true;
}
}
}
return (rotten && !fresh) || (absent && !rotten & !fresh);
};
참고 사이트
https://javascript.plainenglish.io/leetcode-994-rotting-oranges-problem-9596d4f8e923
Comment