-
-
Notifications
You must be signed in to change notification settings - Fork 195
[shinsj4653] Week 04 Solutions #1338
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
Changes from all commits
315d365
6d98663
acf37c0
caca329
9468614
afe0d4a
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,45 @@ | ||
""" | ||
[문제풀이] | ||
# Inputs | ||
- 정수 배열 coins | ||
- 총 돈의 값 amount | ||
# Outputs | ||
- amount 를 채울 수 있는 동전의 가장 적은 수 | ||
- 만약 만들 수 없다면 -1 return | ||
# Constraints | ||
- 1 <= coins.length <= 12 | ||
- 1 <= coins[i] <= 2^31 - 1 | ||
- 0 <= amount <= 10^4 | ||
# Ideas | ||
- 우선 이전 풀이 본 거 연습해보기 | ||
- DP 탑다운 방식으로! 이 문제 풀이를 내가 100% 이해하고 있는게 맞는지 손으로 도식화 해보기로함 | ||
|
||
|
||
[회고] | ||
재귀랑 dp는 다양한 유형을 많이 풀어보는 수 밖에.. | ||
""" | ||
|
||
|
||
class Solution: | ||
def coinChange(self, coins: List[int], amount: int) -> int: | ||
memo = {} | ||
|
||
def dp(amount): | ||
|
||
if amount == 0: | ||
return 0 | ||
|
||
retList = [] | ||
for coin in coins: | ||
if amount - coin >= 0: | ||
if amount - coin not in memo: | ||
memo[amount - coin] = dp(amount - coin) | ||
|
||
if memo[amount - coin] != -1: | ||
retList.append(memo[amount - coin]) | ||
|
||
return min(retList) + 1 if retList else -1 | ||
|
||
return dp(amount) | ||
|
||
|
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. 전체적인 문제 풀이에 대한 아이디어, 흐름, 해설을 통한 개선점까지 같이 적어주시는 부분이 굉장히 좋은 것 같습니다! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
""" | ||
[문제풀이] | ||
# Inputs | ||
- sorted rotated array : nums | ||
- nums안의 요소는 unique | ||
# Outputs | ||
- 배열의 가장 작은 값 Return | ||
# Constraints | ||
- O(logN) 시간대로 풀어야함 | ||
- n == nums.length | ||
- 1 <= n <= 5000 | ||
- -5000 <= nums[i] <= 5000 | ||
- All the integers of nums are unique. | ||
- nums is sorted and rotated between 1 and n times. | ||
# Ideas | ||
그냥 정렬은 O(NlogN) 이어서 불가능 | ||
rotate : 맨 끝의 요소가 맨 처음으로 옴 | ||
이진탐색이 O(logN) 이긴한데..->하지만, 이진탐색은 정렬된 배열에서만 사용가능 | ||
그리고, 이 문제에선 아닌 것 같다 | ||
|
||
끝의 원소를 빼서 stack에 append -> 모두 o(1) | ||
|
||
회전되어 있는 배열의 특성을 활용하여 | ||
-> 끝의 원소 빼고, 그걸 stack 에 넣기 | ||
-> 그리고 stack의 맨 끝 원소보다 nums의 끝 원소가 더 클때 | ||
stack[-1] 이 정답 | ||
-> 근데 이건 o(n) 아닌가?? | ||
|
||
우선 내 풀이 정답 | ||
해설 참고 | ||
-> 내 풀이는 O(n) 이다.. O(logN) 풀이가 필요 | ||
이분탐색 응용문제이다 | ||
|
||
[회고] | ||
|
||
""" | ||
|
||
# 내 풀이 | ||
from collections import deque | ||
|
||
|
||
class Solution: | ||
def findMin(self, nums: List[int]) -> int: | ||
|
||
if len(nums) == 1: | ||
return nums[0] | ||
|
||
nums = deque(nums) | ||
|
||
st = [] | ||
ret = 0 | ||
|
||
while nums: | ||
num = nums.pop() | ||
|
||
if not nums: | ||
ret = num | ||
break | ||
|
||
if num < nums[-1]: | ||
ret = num | ||
break | ||
|
||
return ret | ||
|
||
# 해설 | ||
class Solution: | ||
def findMin(self, nums: List[int]) -> int: | ||
|
||
left, right = 1, len(nums) - 1 | ||
|
||
while left <= right: | ||
mid = (left + right) // 2 | ||
if nums[mid - 1] > nums[mid]: | ||
return nums[mid] | ||
if nums[0] < nums[mid]: | ||
left = mid + 1 | ||
else: | ||
right = mid - 1 | ||
|
||
return nums[0] | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,56 @@ | ||||||
""" | ||||||
[문제풀이] | ||||||
# Inputs | ||||||
- 이진 트리의 root | ||||||
# Outputs | ||||||
- 가장 최고 깊이 | ||||||
# Constraints | ||||||
The number of nodes in the tree is in the range [0, 104]. | ||||||
-100 <= Node.val <= 100 | ||||||
# Ideas | ||||||
dfs, 즉 재귀 돌면서 | ||||||
depth 를 max로 업데이트 하면 될 것 같은 느낌? | ||||||
|
||||||
[회고] | ||||||
내 풀이는 정답 | ||||||
해설 방법도 궁금하여 참고 | ||||||
-> TC, SC도 파악하는 연습! | ||||||
|
||||||
TC: o(n) | ||||||
SC: o(n) | ||||||
|
||||||
""" | ||||||
|
||||||
# 내 풀이 | ||||||
# 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 Solution: | ||||||
def maxDepth(self, root: Optional[TreeNode]) -> int: | ||||||
def dfs(node, depth): | ||||||
if node is None: | ||||||
return depth - 1 | ||||||
|
||||||
return max(dfs(node.left, depth + 1), dfs(node.right, depth + 1)) | ||||||
|
||||||
return dfs(root, 1) | ||||||
# 해설 | ||||||
# bfs 풀이도 존재 | ||||||
class Solution: | ||||||
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. Duplicate 'Solution' class definition may cause unintended overrides. Consider merging the two implementations or renaming one of them.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
def maxDepth(self, root: Optional[TreeNode]) -> int: | ||||||
if not root: | ||||||
return 0 | ||||||
max_depth = 0 | ||||||
stack = [(root, 1)] | ||||||
while stack: | ||||||
node, depth = stack.pop() | ||||||
max_depth = max(depth, max_depth) | ||||||
if node.left: | ||||||
stack.append((node.left, depth + 1)) | ||||||
if node.right: | ||||||
stack.append((node.right, depth + 1)) | ||||||
return max_depth | ||||||
|
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. 풀이에 대해 고민하셨던 부분을 읽어보니 저와 비슷한 고민을 하셨던 것 같아요. 저도 오랫동안 고민하다가 이전 Tree 문제들이 재귀를 이용해 풀이를 진행했던 걸 상기하고 ListNode의 구조를 활용해서 풀이를 했는데, 풀이 과정에 대한 고찰이 꼼꼼하게 적혀있어서 좋았습니다. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
""" | ||
[문제풀이] | ||
# Inputs | ||
- two sorted linked lists | ||
# Outputs | ||
- 두 링크드 리스트를 합쳐서 하나의 정렬된 (오름차순) 리스트 반환 | ||
# Constraints | ||
- The number of nodes in both lists is in the range [0, 50]. | ||
- -100 <= Node.val <= 100 | ||
- Both list1 and list2 are sorted in non-decreasing order. | ||
# Ideas | ||
두 링크드 리스트는 모두 오름차순으로 정렬되어 있음 | ||
-> ListNode는 val, next 로 되어있음 | ||
|
||
우선 두 리스트 이어붙이고, | ||
먼가 리스트 정렬 알고리즘 써야할듯? | ||
리스트라서, 두 노드를 바꾸는 swap() 함수 쓰면서, | ||
왼쪽보다 오른쪽이 작으면 바꾸는 식으로 하면 될듯? | ||
|
||
즉, 붙어있는 두 노드 비교하면서 쭉 돌기 | ||
하지만 인덱스가 없어서 어떻게 순회할지? | ||
-> point라는 기준을 둬서 이 point를 기준으로 prev, next를 만들어서 순회 | ||
-> 근데 prev, next만으로는 swap이 어려워서 2개가 아닌 3개를 둬야할 것 같은데, | ||
구현 방법이 떠오르지 않아서 해설 참고 | ||
|
||
해설 참고 | ||
- 기존 리스트 변경이 아닌, 아예 새로운 리스트를 재창조 하는 방식으로! | ||
|
||
|
||
[회고] | ||
기존 리스트를 swap하려고 하다 보니, 어렵게 생각하게됨.. | ||
|
||
""" | ||
|
||
|
||
# Definition for singly-linked list. | ||
# 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]: | ||
|
||
retList = ListNode(None) | ||
head = retList | ||
|
||
while list1 and list2: | ||
if list1.val < list2.val: | ||
head.next = list1 | ||
list1 = list1.next | ||
|
||
else: | ||
head.next = list2 | ||
list2 = list2.next | ||
|
||
head = head.next | ||
|
||
head.next = list1 or list2 | ||
return retList.next | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,150 @@ | ||||||
""" | ||||||
[문제풀이] | ||||||
# Inputs | ||||||
- board: m*n grid of characters | ||||||
- word: str | ||||||
# Outputs | ||||||
- word 가 grid 안에 있으면 true, 아니면 false | ||||||
# Constraints | ||||||
- 탐색: 상하좌우 | ||||||
- m == board.length | ||||||
- n = board[i].length | ||||||
- 1 <= m, n <= 6 | ||||||
- 1 <= word.length <= 15 | ||||||
|
||||||
- board, word => 무조건 대소문자로 구성 | ||||||
# Ideas | ||||||
1. 퍼지면서 탐색 -> bfs? | ||||||
q = cur.append(i, j, "") | ||||||
q.pop() 해서 | ||||||
if 현재 w 가 word랑 같다면 그 즉시 bfs stop하고 return True | ||||||
만약 bfs 끝까지 했는데도 안나오면 return False | ||||||
|
||||||
bfs: q에 다음 원소 넣을 때 현재 값에 이어붙인문자가 w랑 어떤식으로 비교해야 맞는 조건절이 되는걸까? | ||||||
=> cur_w의 len 값을 i로 사용하려했지만 w가 더 짧으면 idxError 뜰까봐 보류 | ||||||
=> 메모리 초과 오류 뜸.. | ||||||
=> 아..같은 자리를 방문하면 안됨!! 즉, 원복이 필요함! | ||||||
-> 백트래킹으로 풀이 change | ||||||
|
||||||
2. dfs로도 꼭 풀어보기! | ||||||
백트래킹 복습 용으로 굿 | ||||||
|
||||||
board안의 숫자는 오직 대소문자 -> isalpha() 로 체킹 가능 | ||||||
=> 방문하면 0으로 바꾸기 | ||||||
|
||||||
풀기는 풀었지만..7090ms : Beats 7.34% | ||||||
|
||||||
Follow up : Could you use search pruning to make your solution faster with a larger board | ||||||
가지치기 기법 어떻게 도입할까?? | ||||||
=> cur_idx 하나 둬서, AB.. ABC -> 진행 도중, 하나라도 word랑 다르면 바로 그 경로 컷 | ||||||
=> 그래도 4587ms.. Beats 41.00% | ||||||
=> 먼가 더 정석 성능 개선이 필요 | ||||||
|
||||||
해설 참고 | ||||||
=> word_idx를 이용, any문을 이용한 리팩토링 | ||||||
=> 해설 풀이 : 4385ms | ||||||
|
||||||
[회고] | ||||||
idx를 이용한 가지치기 방법 잘 알아두자 | ||||||
""" | ||||||
|
||||||
# from collections import deque | ||||||
# class Solution: | ||||||
# def exist(board, word): | ||||||
# | ||||||
# q = deque([]) | ||||||
# n, m = len(board), len(board[0]) | ||||||
# | ||||||
# q.append((0, 0, board[0][0])) | ||||||
# | ||||||
# dy = [-1, 0, 1, 0] | ||||||
# dx = [0, 1, 0, -1] | ||||||
# | ||||||
# while q: | ||||||
# cur_y, cur_x, cur_w = q.popleft() | ||||||
# | ||||||
# if cur_w == word: | ||||||
# return True | ||||||
# | ||||||
# for i in range(3): | ||||||
# ny = cur_y + dy[i] | ||||||
# nx = cur_x + dx[i] | ||||||
# | ||||||
# if 0 <= ny < n and 0 <= nx < m: | ||||||
# q.append((ny, nx, cur_w + board[ny][nx])) | ||||||
# | ||||||
# return False | ||||||
# | ||||||
# exist([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "ABCCDE") | ||||||
|
||||||
|
||||||
class Solution: | ||||||
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. Multiple definitions of 'Solution' detected. Consider consolidating them into a single class or renaming one to prevent unintended overrides.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
def exist(self, board: List[List[str]], word: str) -> bool: | ||||||
|
||||||
n, m = len(board), len(board[0]) | ||||||
|
||||||
dy = [-1, 0, 1, 0] | ||||||
dx = [0, 1, 0, -1] | ||||||
|
||||||
v = [[False for _ in range(m)] for _ in range(n)] | ||||||
|
||||||
def dfs(y, x, w): | ||||||
#print('y, x : ', y, x) | ||||||
#print('w: ', w) | ||||||
if w == word: | ||||||
return True | ||||||
|
||||||
if len(w) >= len(word): | ||||||
return False | ||||||
|
||||||
for k in range(4): | ||||||
ny = y + dy[k] | ||||||
nx = x + dx[k] | ||||||
|
||||||
if 0 <= ny < n and 0 <= nx < m and not v[ny][nx]: | ||||||
v[ny][nx] = True | ||||||
if dfs(ny, nx, w + board[ny][nx]): | ||||||
return True | ||||||
v[ny][nx] = False | ||||||
|
||||||
for i in range(n): | ||||||
for j in range(m): | ||||||
if not v[i][j] and board[i][j] == word[0]: | ||||||
v[i][j] = True | ||||||
if dfs(i, j, board[i][j]): | ||||||
return True | ||||||
v[i][j] = False | ||||||
|
||||||
return False | ||||||
|
||||||
# 해설 | ||||||
class Solution: | ||||||
def exist(self, board: List[List[str]], word: str) -> bool: | ||||||
|
||||||
n, m = len(board), len(board[0]) | ||||||
|
||||||
dy = [-1, 0, 1, 0] | ||||||
dx = [0, 1, 0, -1] | ||||||
|
||||||
def dfs(y, x, idx): | ||||||
if idx == len(word): | ||||||
return True | ||||||
|
||||||
if not (0 <= y < n and 0 <= x < m): | ||||||
return False | ||||||
|
||||||
if board[y][x] != word[idx]: | ||||||
return False | ||||||
|
||||||
temp = board[y][x] | ||||||
board[y][x] = "" | ||||||
|
||||||
for i in range(4): | ||||||
if dfs(y + dy[i], x + dx[i], idx + 1): | ||||||
return True | ||||||
|
||||||
board[y][x] = temp | ||||||
return False | ||||||
|
||||||
return any(dfs(i, j, 0) for i in range(n) for j in range(m)) | ||||||
|
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.
Consider caching the result of dp(amount) by storing it in memo after computation to avoid repeated calculations and improve performance.
Copilot uses AI. Check for mistakes.