-
-
Notifications
You must be signed in to change notification settings - Fork 195
[hi-rachel] Week 04 Solutions #1340
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
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
414e9c4
merge-two-sorted-lists solution(py, ts)
hi-rachel f50a050
maximum-depth-of-binary-tree solution (py, ts)
hi-rachel 91e86a9
find-minimum-in-rotated-sorted-array (ts, py)
hi-rachel 3c35048
coin-change solution (py)
hi-rachel 8deee8d
coin-change solution (ts)
hi-rachel 412bf7b
word-search solution (py)
hi-rachel File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
|
||
# BFS -> 먼저 찾는 해답이 가장 적은 연산/가장 짧은 거리 -> 가장 적은 count부터 계산해 최소한의 동전 수 보장 | ||
# O(amount * n) time, O(amount) space | ||
|
||
from collections import deque | ||
|
||
class Solution: | ||
def coinChange(self, coins: List[int], amount: int) -> int: | ||
queue = deque([(0, 0)]) # (동전 개수, 현재 금액) | ||
visited = set() | ||
while queue: | ||
count, total = queue.popleft() | ||
if total == amount: | ||
return count | ||
if total in visited: | ||
continue | ||
visited.add(total) | ||
for coin in coins: | ||
if total + coin <= amount: | ||
queue.append((count + 1, total + coin)) | ||
return - 1 | ||
|
||
|
||
# DP 풀이 | ||
# 어떤 금액을 만드는데 필요한 동전 개수를 알면, 그 금액보다 큰 금액을 만드는데 필요한 동전 개수도 알 수 있다. | ||
# dp[i] = min(dp[i], dp[i - coin] + 1) | ||
# O(amount * n) time, O(amount) space | ||
|
||
class Solution: | ||
def coinChange(self, coins: List[int], amount: int) -> int: | ||
dp = [0] + [amount + 1] * amount | ||
|
||
for coin in coins: | ||
for i in range(coin, amount + 1): | ||
dp[i] = min(dp[i], dp[i - coin] + 1) | ||
|
||
return dp[amount] if dp[amount] < amount + 1 else -1 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
function coinChange(coins: number[], amount: number): number { | ||
const dp = [0, ...new Array(amount).fill(amount + 1)]; | ||
for (let i = 0; i <= amount; i++) { | ||
for (const coin of coins) { | ||
if (coin <= i) { | ||
dp[i] = Math.min(dp[i], dp[i - coin] + 1); | ||
} | ||
} | ||
} | ||
return dp[amount] < amount + 1 ? dp[amount] : -1; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# 회전된 오름차순 배열에서 최소값을 이진 탐색으로 찾아라 | ||
|
||
# O(N) time, O(1) space -> 시간 복잡도 충족 x | ||
class Solution: | ||
def findMin(self, nums: List[int]) -> int: | ||
for i in range(1, len(nums)): | ||
if nums[i - 1] > nums[i]: | ||
return nums[i] | ||
return nums[0] | ||
|
||
|
||
class Solution: | ||
|
||
|
||
# 이진 탐색 풀이 | ||
# O(log n) time, O(1) space | ||
class Solution: | ||
def findMin(self, nums: List[int]) -> int: | ||
low, high = 1, len(nums) - 1 | ||
while low <= high: | ||
mid = (low + high) // 2 | ||
if nums[mid - 1] > nums[mid]: | ||
return nums[mid] | ||
if nums[0] < nums[mid]: | ||
low = mid + 1 | ||
else: | ||
high = mid - 1 | ||
return nums[0] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
function findMin(nums: number[]): number { | ||
let low = 0, | ||
high = nums.length - 1; | ||
|
||
while (low <= high) { | ||
let mid = Math.floor((low + high) / 2); | ||
if (nums[mid - 1] > nums[mid]) { | ||
return nums[mid]; // 회전이 일어난 곳 | ||
} | ||
if (nums[0] < nums[mid]) { | ||
low = mid + 1; // 왼쪽은 이미 정렬되어 있어, 오른쪽으로 이동 | ||
} else { | ||
high = mid - 1; // 왼쪽으로 이동 | ||
} | ||
} | ||
return nums[0]; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# O(n) time, 모든 노드를 한 번씩 방문 | ||
# O(h) for DFS / O(w) for BFS space, DFS는 재귀 호출 깊이 (h = 트리 높이), BFS는 큐에 들어가는 최대 노드 수 (w = 최대 너비) | ||
|
||
# Definition for a binary tree node. | ||
# class TreeNode: | ||
# def __init__(self, val=0, left=None, right=None): | ||
# self.val = val | ||
# self.left = left | ||
# self.right = right | ||
|
||
|
||
class TreeNode: | ||
def __init__(self, val=0, left=None, right=None): | ||
self.val = val | ||
self.left = left | ||
self.right = right | ||
|
||
# BFS 풀이 | ||
from collections import deque | ||
|
||
class Solution: | ||
def maxDepth(self, root: Optional[TreeNode]) -> int: | ||
if not root: | ||
return 0 | ||
|
||
queue = deque([root]) | ||
depth = 0 | ||
|
||
while queue: | ||
for _ in range(len(queue)): | ||
node = queue.popleft() | ||
if node.left: | ||
queue.append(node.left) | ||
if node.right: | ||
queue.append(node.right) | ||
depth += 1 | ||
return depth | ||
|
||
# DFS 풀이 | ||
class Solution: | ||
def maxDepth(self, root: Optional[TreeNode]) -> int: | ||
if not root: | ||
return 0 | ||
return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/** | ||
* Definition for a binary tree node. | ||
* class TreeNode { | ||
* val: number | ||
* left: TreeNode | null | ||
* right: TreeNode | null | ||
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { | ||
* this.val = (val===undefined ? 0 : val) | ||
* this.left = (left===undefined ? null : left) | ||
* this.right = (right===undefined ? null : right) | ||
* } | ||
* } | ||
*/ | ||
|
||
// O(n) time, 모든 노드를 한 번씩 방문 | ||
// O(h) for DFS / O(w) for BFS space, DFS는 재귀 호출 깊이 (h = 트리 높이), BFS는 큐에 들어가는 최대 노드 수 (w = 최대 너비) | ||
|
||
class TreeNode { | ||
val: number; | ||
left: TreeNode | null; | ||
right: TreeNode | null; | ||
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { | ||
this.val = val === undefined ? 0 : val; | ||
this.left = left === undefined ? null : left; | ||
this.right = right === undefined ? null : right; | ||
} | ||
} | ||
|
||
// BFS 풀이 | ||
function maxDepth(root: TreeNode | null): number { | ||
if (root === null) return 0; | ||
|
||
const queue: TreeNode[] = [root]; | ||
let depth = 0; | ||
|
||
while (queue.length > 0) { | ||
const levelSize = queue.length; | ||
|
||
for (let i = 0; i < levelSize; i++) { | ||
const node = queue.shift(); | ||
if (node) { | ||
if (node.left) queue.push(node.left); | ||
if (node.right) queue.push(node.right); | ||
} | ||
} | ||
depth++; | ||
} | ||
return depth; | ||
} | ||
|
||
// DFS 풀이 | ||
// function maxDepth(root: TreeNode | null): number { | ||
// if (root === null) return 0; | ||
// const left = maxDepth(root.left); | ||
// const right = maxDepth(root.right); | ||
// return Math.max(left, right) + 1; | ||
// } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# O(n + m) time, n = list1의 노드 수 / m = list2의 노드 수 | ||
# O(1) space, 연결된 새 리스트는 기존 노드들을 재사용해서 만듬 | ||
|
||
# Definition for singly-linked list. | ||
# class ListNode: | ||
# def __init__(self, val=0, next=None): | ||
# self.val = val | ||
# self.next = next | ||
|
||
class ListNode: | ||
def __init__(self, val=0, next=None): | ||
self.val = val | ||
self.next = next | ||
|
||
class Solution: | ||
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: | ||
dummy = ListNode() | ||
tail = dummy | ||
|
||
while list1 and list2: | ||
if list1.val < list2.val: | ||
tail.next = list1 | ||
list1 = list1.next | ||
else: | ||
tail.next = list2 | ||
list2 = list2.next | ||
tail = tail.next | ||
|
||
if list1: | ||
tail.next = list1 | ||
if list2: | ||
tail.next = list2 | ||
return dummy.next |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/** | ||
* Definition for singly-linked list. | ||
* class ListNode { | ||
* val: number | ||
* next: ListNode | null | ||
* constructor(val?: number, next?: ListNode | null) { | ||
* this.val = (val===undefined ? 0 : val) | ||
* this.next = (next===undefined ? null : next) | ||
* } | ||
* } | ||
*/ | ||
|
||
class ListNode { | ||
val: number; | ||
next: ListNode | null; | ||
constructor(val?: number, next?: ListNode | null) { | ||
this.val = val === undefined ? 0 : val; | ||
this.next = next === undefined ? null : next; | ||
} | ||
} | ||
|
||
function mergeTwoLists( | ||
list1: ListNode | null, | ||
list2: ListNode | null | ||
): ListNode | null { | ||
const dummy = new ListNode(); | ||
let tail = dummy; | ||
while (list1 !== null && list2 !== null) { | ||
if (list1.val < list2.val) { | ||
tail.next = list1; | ||
list1 = list1.next; | ||
} else { | ||
tail.next = list2; | ||
list2 = list2.next; | ||
} | ||
tail = tail.next; | ||
} | ||
if (list1 !== null) { | ||
tail.next = list1; | ||
} | ||
if (list2 !== null) { | ||
tail.next = list2; | ||
} | ||
return dummy.next; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# DFS 풀이 | ||
# board 높이: m, 넓이: n, w: 단어의 길이 | ||
# TC: (m * n * 4^w) -> 4^w 상하좌우 탐색 * 글자판 내의 모든 좌표를 상대로 수행함 | ||
# SC: O(m * n + w) -> traversing 집합 메모리는 글자판의 크기의 비례 + dfs 호출 스택의 깊이가 단어의 길이에 비례해 증가 | ||
|
||
class Solution: | ||
def exist(self, board: List[List[str]], word: str) -> bool: | ||
n_rows, n_cols = len(board), len(board[0]) | ||
traversing = set() | ||
|
||
def dfs(row, col, idx): | ||
if idx == len(word): | ||
return True | ||
if not (0 <= row < n_rows and 0 <= col < n_cols): | ||
return False | ||
if (row, col) in traversing: | ||
return False | ||
if board[row][col] != word[idx]: | ||
return False | ||
|
||
traversing.add((row, col)) | ||
# 상하좌우 탐색 | ||
for (r, c) in [(-1, 0), (1, 0), (0, -1), (0, 1)]: | ||
if dfs(row + r, col + c, idx + 1): | ||
return True | ||
traversing.remove((row, col)) | ||
return False | ||
|
||
for i in range(n_rows): | ||
for j in range(n_cols): | ||
if dfs(i, j, 0): | ||
return True | ||
return False |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
@hi-rachel 님 안녕하세요. 이번 주도 고생하셨습니다. 저는 문제를 풀 때 dp로 접근하는 것을 어려워하는 편이라서, 특히 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.
그리고 전체적으로 풀이가 깔끔해서 나중에 공부할 때도 참고가 될 것 같습니다. 감사합니다!
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.
@KwonNayeon 님 안녕하세요 :) 저만 dp가 어려운게 아니였군여ㅜㅜ 저도 dp 문제는 이해 안가는 문제들이 많아서 힘들었는데 다행히 이 문제는 알고달레의 설명을 보고 이해했습니다. 저도 못풀어서 알고달레 풀이를 참고했는데 자세한 풀이를 원하실 때 추천드립니다. 감사합니다~
https://www.algodale.com/problems/coin-change/
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.
저도 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.
@KwonNayeon dp + 재귀 + 백트래킹 넘나 어려워요.. 이번 스터디 끝날 때쯤에는 사고가 넓어져있길! 같이 파이팅합시다! 감사합니다.