Skip to content

Commit bc97a50

Browse files
authored
[ICE0208] WEEK 04 Solutions (#2744)
* merge two sorted lists * maximum depth of binary tree * find minimum in rotated sorted array * word search * coin change
1 parent 5a7ca16 commit bc97a50

5 files changed

Lines changed: 178 additions & 0 deletions

File tree

coin-change/ICE0208.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
class Solution {
2+
/**
3+
* 시간 복잡도: O(amount * coins.length)
4+
* 공간 복잡도: O(amount)
5+
*/
6+
public int coinChange(int[] coins, int amount) {
7+
// 필요한 동전의 최대 개수는 amount개이므로,
8+
// amount + 1은 만들 수 없는 상태를 나타내기에 충분하다.
9+
int impossible = amount + 1;
10+
11+
int[] dp = new int[amount + 1];
12+
Arrays.fill(dp, impossible);
13+
dp[0] = 0;
14+
15+
for (int currentAmount = 1; currentAmount <= amount; currentAmount++) {
16+
for (int coin : coins) {
17+
if (coin > currentAmount) {
18+
continue;
19+
}
20+
21+
dp[currentAmount] = Math.min(
22+
dp[currentAmount],
23+
dp[currentAmount - coin] + 1
24+
);
25+
}
26+
}
27+
28+
return dp[amount] == impossible ? -1 : dp[amount];
29+
}
30+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
class Solution {
2+
public int findMin(int[] nums) {
3+
return binarySearch(nums, 0, nums.length -1);
4+
}
5+
6+
private int binarySearch(int[] nums, int left, int right) {
7+
// 탐색 범위에 원소가 하나만 남은 경우
8+
if (left == right) {
9+
return nums[left];
10+
}
11+
12+
// [1] 현재 범위가 이미 오름차순이라면 첫 번째 값이 최솟값!
13+
if (nums[left] < nums[right]) {
14+
return nums[left];
15+
}
16+
17+
int mid = left + (right - left) / 2;
18+
// [2-1] 왼쪽 구간이 정렬되어 있다면 최솟값은 오른쪽 구간에 있다
19+
if (nums[left] <= nums[mid]) {
20+
return binarySearch(nums, mid + 1, right);
21+
}
22+
// [2-2] 회전 지점이 왼쪽 구간에 있다.
23+
return binarySearch(nums, left, mid);
24+
}
25+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class Solution {
2+
public int maxDepth(TreeNode root) {
3+
if (root == null) {
4+
return 0;
5+
}
6+
7+
int leftDepth = maxDepth(root.left);
8+
int rightDepth = maxDepth(root.right);
9+
10+
return Math.max(leftDepth, rightDepth) + 1;
11+
}
12+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
class Solution {
2+
/**
3+
* 두 정렬된 연결 리스트의 기존 노드를 재사용하여 하나의 정렬된 리스트로 병합한다.
4+
*
5+
* 시간 복잡도: O(n + m)
6+
* - n: list1의 길이
7+
* - m: list2의 길이
8+
*
9+
* 공간 복잡도: O(1)
10+
* - 새로운 노드를 생성하지 않고 기존 노드를 재사용한다.
11+
*/
12+
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
13+
ListNode dummyHead = new ListNode();
14+
ListNode tail = dummyHead;
15+
16+
// 두 리스트를 순회하며 더 작은 노드를 결과 리스트의 뒤에 연결한다.
17+
while (list1 != null && list2 != null) {
18+
if (list1.val <= list2.val) {
19+
tail.next = list1;
20+
list1 = list1.next;
21+
} else {
22+
tail.next = list2;
23+
list2 = list2.next;
24+
}
25+
26+
tail = tail.next;
27+
}
28+
29+
// 한쪽 리스트가 끝나면 다른 리스트의 남은 노드들을 그대로 연결한다.
30+
tail.next = list1 != null ? list1 : list2;
31+
32+
return dummyHead.next;
33+
}
34+
}

word-search/ICE0208.java

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
class Solution {
2+
private static final int[][] DIRECTIONS = {
3+
{-1, 0},
4+
{1, 0},
5+
{0, -1},
6+
{0, 1}
7+
};
8+
9+
private char[][] board;
10+
private String word;
11+
private boolean[][] visited;
12+
private int rows;
13+
private int cols;
14+
15+
public boolean exist(char[][] board, String word) {
16+
this.board = board;
17+
this.word = word;
18+
this.rows = board.length;
19+
this.cols = board[0].length;
20+
this.visited = new boolean[rows][cols];
21+
22+
// 단어가 전체 칸보다 길면 경로를 만들 수 없다.
23+
if (word.length() > rows * cols) {
24+
return false;
25+
}
26+
27+
for (int row = 0; row < rows; row++) {
28+
for (int col = 0; col < cols; col++) {
29+
// 첫 문자가 일치하는 위치에서만 탐색을 시작한다.
30+
if (board[row][col] == word.charAt(0)
31+
&& search(row, col, 0)) {
32+
return true;
33+
}
34+
}
35+
}
36+
37+
return false;
38+
}
39+
40+
private boolean search(int row, int col, int wordIndex) {
41+
// 이미 현재 경로에서 사용한 칸이거나 문자가 다르면 탐색을 중단한다.
42+
if (visited[row][col]
43+
|| board[row][col] != word.charAt(wordIndex)) {
44+
return false;
45+
}
46+
47+
// 마지막 문자까지 일치했다면 단어를 찾은 것이다.
48+
if (wordIndex == word.length() - 1) {
49+
return true;
50+
}
51+
52+
visited[row][col] = true;
53+
54+
for (int[] direction : DIRECTIONS) {
55+
int nextRow = row + direction[0];
56+
int nextCol = col + direction[1];
57+
58+
if (!isInBounds(nextRow, nextCol)) {
59+
continue;
60+
}
61+
62+
if (search(nextRow, nextCol, wordIndex + 1)) {
63+
visited[row][col] = false;
64+
return true;
65+
}
66+
}
67+
68+
// 다른 경로에서 현재 칸을 다시 사용할 수 있도록 방문 상태를 복구한다.
69+
visited[row][col] = false;
70+
return false;
71+
}
72+
73+
private boolean isInBounds(int row, int col) {
74+
return row >= 0 && row < rows
75+
&& col >= 0 && col < cols;
76+
}
77+
}

0 commit comments

Comments
 (0)