-
-
Notifications
You must be signed in to change notification settings - Fork 362
[ICE0208] WEEK 07 Solutions #2798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| import java.util.ArrayDeque; | ||
| import java.util.Deque; | ||
|
|
||
| class Solution { | ||
| private static final int[][] DIRECTIONS = { | ||
| {0, 1}, | ||
| {0, -1}, | ||
| {1, 0}, | ||
| {-1, 0} | ||
| }; | ||
|
|
||
| private static final char WATER = '0'; | ||
| private static final char LAND = '1'; | ||
|
|
||
| private record Position(int row, int column) { | ||
| } | ||
|
|
||
| /** | ||
| * 격자를 순회하며 아직 방문하지 않은 육지를 발견할 때마다 | ||
| * 연결된 하나의 섬을 반복형 DFS로 모두 방문 처리한다. | ||
| * | ||
| * 시간 복잡도: O(m * n) | ||
| * 공간 복잡도: O(m * n) | ||
| */ | ||
| public int numIslands(char[][] grid) { | ||
| int islandCount = 0; | ||
|
|
||
| for (int row = 0; row < grid.length; row++) { | ||
| for (int column = 0; column < grid[row].length; column++) { | ||
| if (grid[row][column] != LAND) { | ||
| continue; | ||
| } | ||
|
|
||
| // 아직 방문하지 않은 육지는 새로운 섬의 시작점이다. | ||
| islandCount++; | ||
| markIslandAsVisited(grid, row, column); | ||
| } | ||
| } | ||
|
|
||
| return islandCount; | ||
| } | ||
|
|
||
| /** | ||
| * 시작 위치와 상하좌우로 연결된 모든 육지를 방문 처리한다. | ||
| * 재귀 호출로 인한 스택 오버플로를 피하기 위해 별도의 스택을 사용한다. | ||
| */ | ||
| private static void markIslandAsVisited( | ||
| char[][] grid, | ||
| int startRow, | ||
| int startColumn | ||
| ) { | ||
| Deque<Position> stack = new ArrayDeque<>(); | ||
| stack.push(new Position(startRow, startColumn)); | ||
|
|
||
| // 스택에 넣는 시점에 방문 처리하여 같은 위치가 중복으로 들어가는 것을 방지한다. | ||
| grid[startRow][startColumn] = WATER; | ||
|
|
||
| while (!stack.isEmpty()) { | ||
| Position current = stack.pop(); | ||
|
|
||
| for (int[] direction : DIRECTIONS) { | ||
| int nextRow = current.row() + direction[0]; | ||
| int nextColumn = current.column() + direction[1]; | ||
|
|
||
| if (!isInBounds(grid, nextRow, nextColumn)) { | ||
| continue; | ||
| } | ||
|
|
||
| if (grid[nextRow][nextColumn] != LAND) { | ||
| continue; | ||
| } | ||
|
|
||
| grid[nextRow][nextColumn] = WATER; | ||
| stack.push(new Position(nextRow, nextColumn)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private static boolean isInBounds( | ||
| char[][] grid, | ||
| int row, | ||
| int column | ||
| ) { | ||
| return row >= 0 | ||
| && row < grid.length | ||
| && column >= 0 | ||
| && column < grid[0].length; | ||
| } | ||
| } |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석set-matrix-zeroes/ICE0208.javaimport java.util.Arrays;
class Solution {
public void setZeroes(int[][] matrix) {
int rows = matrix.length;
int cols = matrix[0].length;
// 첫 번째 행과 열은 marker로 사용하므로, 원래 0이 있었는지 별도로 저장한다.
boolean firstRowHasZero = false;
for (int col = 0; col < cols; ++col) {
if (matrix[0][col] == 0) {
firstRowHasZero = true;
break;
}
}
boolean firstColumnHasZero = false;
for (int row = 0; row < rows; ++row) {
if (matrix[row][0] == 0) {
firstColumnHasZero = true;
break;
}
}
// 첫 번째 행과 열을 각 행과 열의 zero marker로 사용한다.
for (int row = 1; row < rows; ++row) {
for (int col = 1; col < cols; ++col) {
if (matrix[row][col] == 0) {
matrix[row][0] = 0;
matrix[0][col] = 0;
}
}
}
// marker를 기준으로 내부 원소를 0으로 변경한다.
for (int row = 1; row < rows; ++row) {
for (int col = 1; col < cols; ++col) {
if (matrix[row][0] == 0 || matrix[0][col] == 0) {
matrix[row][col] = 0;
}
}
}
if (firstRowHasZero) {
Arrays.fill(matrix[0], 0);
}
if (firstColumnHasZero) {
for (int row = 0; row < rows; ++row) {
matrix[row][0] = 0;
}
}
}
}
📊 시간/공간 복잡도 분석
피드백: 입력 행렬에 추가적인 공간을 사용하지 않고, 첫 행/열을 마커로 활용하여 전체 원소를 한 번씩 스캔한다. 개선 제안: 현재 구현이 적절해 보입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| import java.util.Arrays; | ||
|
|
||
| class Solution { | ||
| public void setZeroes(int[][] matrix) { | ||
| int rows = matrix.length; | ||
| int cols = matrix[0].length; | ||
|
|
||
| // 첫 번째 행과 열은 marker로 사용하므로, 원래 0이 있었는지 별도로 저장한다. | ||
| boolean firstRowHasZero = false; | ||
| for (int col = 0; col < cols; ++col) { | ||
| if (matrix[0][col] == 0) { | ||
| firstRowHasZero = true; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| boolean firstColumnHasZero = false; | ||
| for (int row = 0; row < rows; ++row) { | ||
| if (matrix[row][0] == 0) { | ||
| firstColumnHasZero = true; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| // 첫 번째 행과 열을 각 행과 열의 zero marker로 사용한다. | ||
| for (int row = 1; row < rows; ++row) { | ||
| for (int col = 1; col < cols; ++col) { | ||
| if (matrix[row][col] == 0) { | ||
| matrix[row][0] = 0; | ||
| matrix[0][col] = 0; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // marker를 기준으로 내부 원소를 0으로 변경한다. | ||
| for (int row = 1; row < rows; ++row) { | ||
| for (int col = 1; col < cols; ++col) { | ||
| if (matrix[row][0] == 0 || matrix[0][col] == 0) { | ||
| matrix[row][col] = 0; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (firstRowHasZero) { | ||
| Arrays.fill(matrix[0], 0); | ||
| } | ||
|
|
||
| if (firstColumnHasZero) { | ||
| for (int row = 0; row < rows; ++row) { | ||
| matrix[row][0] = 0; | ||
| } | ||
| } | ||
| } | ||
| } |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석unique-paths/ICE0208.javaimport java.util.Arrays;
class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
// 첫 번째 행과 열은 한 방향으로만 이동해 도달할 수 있으므로 1로 초기화합니다.
initializeBaseCases(dp);
for (int row = 1; row < m; ++row) {
for (int col = 1; col < n; ++col) {
dp[row][col] = dp[row - 1][col] + dp[row][col - 1];
}
}
return dp[m - 1][n - 1];
}
/**
* DP 배열의 첫 번째 행과 첫 번째 열을 1로 초기화합니다.
* @param dp 초기화할 DP 배열
*/
private static void initializeBaseCases(int[][] dp) {
int rows = dp.length;
int cols = dp[0].length;
for (int row = 0; row < rows; row++) {
dp[row][0] = 1;
}
for (int col = 0; col < cols; col++) {
dp[0][col] = 1;
}
}
}
class Solution2 {
public int uniquePaths(int m, int n) {
int[] dp = new int[n];
Arrays.fill(dp, 1);
for (int row = 1; row < m; ++row) {
for (int col = 1; col < n; ++col) {
dp[col] += dp[col - 1];
}
}
return dp[n - 1];
}
}
📊 시간/공간 복잡도 분석
풀이 1:
|
| 복잡도 | |
|---|---|
| Time | O(m*n) |
| Space | O(m*n) |
피드백: 2차원 DP 배열을 사용해 이웃 셀의 합으로 현재 셀의 경로 수를 계산합니다.
개선 제안: 현재 구현은 명확하지만 메모리 사용을 줄이려면 공간 최적화 버전(1차원 DP)을 사용할 수 있습니다.
풀이 2: Solution2.uniquePaths — Time: O(m*n) / Space: O(n)
| 복잡도 | |
|---|---|
| Time | O(m*n) |
| Space | O(n) |
피드백: 1차원 배열 dp를 통해 메모리 사용량을 줄였고, 각 행마다 이전 열의 값을 이용해 현재 값을 업데이트한다.
개선 제안: 추가적으로 커스텀 최적화나 초기화 로직을 간소화해도 좋다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🏷️ 알고리즘 패턴 분석
unique-paths/ICE0208.java
import java.util.Arrays;
class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
// 첫 번째 행과 열은 한 방향으로만 이동해 도달할 수 있으므로 1로 초기화합니다.
initializeBaseCases(dp);
for (int row = 1; row < m; ++row) {
for (int col = 1; col < n; ++col) {
dp[row][col] = dp[row - 1][col] + dp[row][col - 1];
}
}
return dp[m - 1][n - 1];
}
/**
* DP 배열의 첫 번째 행과 첫 번째 열을 1로 초기화합니다.
* @param dp 초기화할 DP 배열
*/
private static void initializeBaseCases(int[][] dp) {
int rows = dp.length;
int cols = dp[0].length;
for (int row = 0; row < rows; row++) {
dp[row][0] = 1;
}
for (int col = 0; col < cols; col++) {
dp[0][col] = 1;
}
}
}
class Solution2 {
public int uniquePaths(int m, int n) {
int[] dp = new int[n];
Arrays.fill(dp, 1);
for (int row = 1; row < m; ++row) {
for (int col = 1; col < n; ++col) {
dp[col] += dp[col - 1];
}
}
return dp[n - 1];
}
}- 패턴: Dynamic Programming, Monotonic Stack
- 설명: 두 가지 풀이 모두 DP를 이용한 경로 수 계산 패턴으로 각 셀의 경로 수를 합산합니다. 또한 두 번째 풀이에서 1차원 DP 배열로 공간 최적화하는 일반적 DP 패턴이 보입니다.
📊 시간/공간 복잡도 분석
| 복잡도 | |
|---|---|
| Time | O(m*n) |
| Space | O(m*n) |
피드백: 2D 배열 버전은 직관적이고 이해하기 쉽고, 1D 배열 버전은 공간을 절약합니다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| import java.util.Arrays; | ||
|
|
||
| class Solution { | ||
| public int uniquePaths(int m, int n) { | ||
| int[][] dp = new int[m][n]; | ||
| // 첫 번째 행과 열은 한 방향으로만 이동해 도달할 수 있으므로 1로 초기화합니다. | ||
| initializeBaseCases(dp); | ||
|
|
||
| for (int row = 1; row < m; ++row) { | ||
| for (int col = 1; col < n; ++col) { | ||
| dp[row][col] = dp[row - 1][col] + dp[row][col - 1]; | ||
| } | ||
| } | ||
|
|
||
| return dp[m - 1][n - 1]; | ||
| } | ||
|
|
||
| /** | ||
| * DP 배열의 첫 번째 행과 첫 번째 열을 1로 초기화합니다. | ||
| * @param dp 초기화할 DP 배열 | ||
| */ | ||
| private static void initializeBaseCases(int[][] dp) { | ||
| int rows = dp.length; | ||
| int cols = dp[0].length; | ||
|
|
||
| for (int row = 0; row < rows; row++) { | ||
| dp[row][0] = 1; | ||
| } | ||
| for (int col = 0; col < cols; col++) { | ||
| dp[0][col] = 1; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| class Solution2 { | ||
| public int uniquePaths(int m, int n) { | ||
| int[] dp = new int[n]; | ||
| Arrays.fill(dp, 1); | ||
|
|
||
| for (int row = 1; row < m; ++row) { | ||
| for (int col = 1; col < n; ++col) { | ||
| dp[col] += dp[col - 1]; | ||
| } | ||
| } | ||
|
|
||
| return dp[n - 1]; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🏷️ 알고리즘 패턴 분석
number-of-islands/ICE0208.java
📊 시간/공간 복잡도 분석
피드백: 두 방향으로의 인접만 확장하는 DFS로 전체 격자를 한 번씩 방문하고, 방문 시 육지를 WATER로 표시해 중복 방문을 막는다.
개선 제안: 현재 구현이 적절해 보입니다.