Minimum Number of Days to Disconnect Island
아이디어 자체를 생각해내는 것은 어렵지 않은데, 그 아이디어를 코드로 옮기는 건 어려운 문제였다.
결국 다른 사람의 코드를 보고 풀었다.
해당 문제의 기본 아이디어는 다음과 같다.
- Island가 0이거나 2이상이면 더이상 계산할 필요가 없다.
- 어떠한 경우에도 2이상의 삭제는 불필요 하다.
최악의 경우 [[1,1,1],[1,1,1]] 이라고 해도 (0,0)의 1은 우측 및 하단을 자르면 Island는 2개로 나누어 진다.
[1,1] 이렇게 하나의 island로 나와서 결국 2개를 다 삭제 해야 한다고 해도 최대 2개이다.
[1,1,1] 이 이상의 경우는 가운데 한개를 삭제 하는 것으로 마무리 된다.
결국 답은 2이상을 넘지 못한다.
그럼으로 한개를 삭제하는 것으로 만족하는를 확인 하는게 중요하다.
전 grid를 돌면서 Island하나씩 삭제하고 island가 2개로 갈라지는지 확인 하는 것으로 끝이다.
해당 코드는 타잔 알고리즘으로도 가능하다.
시간 복잡도는
- 최초 Island search하는데 O(grid size)
- 전 grid를 돌면서 island 삭제 하는데 grid size * island가 몇개인지 확인 하는데 grid size가 필요 하다. O(grid size^2)
그러나 cell이 4방향으로 dfs하는 것을 생각 한다면 O(grid size^4) 까지 생각해 볼 수 있다.
- Space Complexity는 dp 하나만 만들고 삭제하는 방식이라 O(n)이면 된다.
var minDays = function(grid) {
let initIsland = getNumIsland(grid);
if(initIsland == 0 || initIsland == 2) return 0;
for(let i = 0; i < grid.length ; i++){
for(let j = 0; j < grid[0].length; j++){
if(grid[i][j] == 1) {
if(getNumIsland(grid,i,j) != 1) return 1;
}
}
}
return 2;
function getNumIsland(grid,row=-1,col=-1){
let count = 0;
let dp = new Array(grid.length).fill(0).map(()=>new Array(grid[0].length).fill(0));
if(0 <= row) dp[row][col] = 1;
for(let i = 0; i < grid.length ; i++){
for(let j = 0; j < grid[0].length; j++){
if(grid[i][j] == 1 && 0 == dp[i][j]){
count++;
if(1 < count) return 2;
journeyIsland(i,j,dp);
}
}
}
return count;
}
function journeyIsland(row, col, dp){
if(row < 0 || dp.length <= row || col < 0 || dp[0].length <= col) return;
if(!(grid[row][col] == 1 && dp[row][col] == 0)) return;
dp[row][col] = 1;
journeyIsland(row - 1, col, dp);
journeyIsland(row + 1, col, dp);
journeyIsland(row, col - 1, dp);
journeyIsland(row, col + 1, dp);
}
};
타잔 알고리즘으로 풀었다. 속도와 Memory 사용이 많이 줄었다.
상기 알고리즘은 모든 island cell에 대해서 island 갯수를 계산 했다면, 타잔은 단 한번만 island cell을 순회 하고 끝낸다.
코드상으로는 for문내에 dfs를 쓴것으로 보이나 그렇지 않다 for문은 island cell을 찾으면 그 이상 순회 하지 않는다
O(grid length), space O(N)
var minDays = function(grid) {
let cellsCount = 0;
let bridge = new Array();
let initIsland = getNumIsland(grid);
if(initIsland == 0 || initIsland == 2) return 0;
if(cellsCount == 2) return 2;
let dp = new Array(grid.length).fill(0).map(()=>new Array(grid[0].length).fill(0));
for(let i = 0; i < grid.length ; i++){
for(let j = 0; j < grid[0].length; j++){
if(grid[i][j] == 1) {
tarjan(grid,i,j,dp,1);
break;
}
}
}
if(0 < bridge.length) return 1;
return 2;
function tarjan(grid,row,col,dp,count,dir=-1){
if(0 < dp[row][col]) return dp[row][col];
dp[row][col] = count;
let min = Number.MAX_VALUE;
if(col + 1 < grid[0].length && grid[row][col+1] == 1 && dir != 1) {
min = Math.min(min, tarjan(grid, row,col + 1,dp,count+1,3));
}
if(row + 1 < grid.length && grid[row+1][col] == 1 && dir != 0) {
min = Math.min(min, tarjan(grid, row+1,col,dp,count+1,2));
}
if(0 <= col - 1 && grid[row][col-1] == 1 && dir != 3) {
min = Math.min(min, tarjan(grid, row,col - 1,dp,count+1,1));
}
if(0 <= row - 1 && grid[row-1][col] == 1 && dir != 2) {
min = Math.min(min, tarjan(grid, row-1,col,dp,count+1,0));
}
if(count < min) bridge.push([row,col]);
else dp[row][col] = min;
return Math.min(count, min);
}
function getNumIsland(grid,row=-1,col=-1){
let count = 0;
let dp = new Array(grid.length).fill(0).map(()=>new Array(grid[0].length).fill(0));
if(0 <= row) dp[row][col] = 1;
for(let i = 0; i < grid.length ; i++){
for(let j = 0; j < grid[0].length; j++){
if(grid[i][j] == 1) cellsCount++;
if(grid[i][j] == 1 && 0 == dp[i][j]){
count++;
if(1 < count) return 2;
journeyIsland(i,j,dp);
}
}
}
return count;
}
function journeyIsland(row, col, dp){
if(row < 0 || dp.length <= row || col < 0 || dp[0].length <= col) return;
if(!(grid[row][col] == 1 && dp[row][col] == 0)) return;
dp[row][col] = 1;
journeyIsland(row - 1, col, dp);
journeyIsland(row + 1, col, dp);
journeyIsland(row, col - 1, dp);
journeyIsland(row, col + 1, dp);
}
};
'Problem Solving' 카테고리의 다른 글
완주하지 못한 선수 (0) | 2020.09.02 |
---|---|
크레인 인형뽑기 게임 (0) | 2020.09.01 |
1567. Maximum Length of Subarray With Positive Product (0) | 2020.09.01 |
Convert Sorted Array to Binary Search Tree (0) | 2020.08.27 |
Validate Binary Search Tree (0) | 2020.08.27 |