-
-
Notifications
You must be signed in to change notification settings - Fork 362
[daehyun99] WEEK 04 Solutions #2750
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
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,18 @@ | ||
| class Solution: | ||
| def findMin(self, nums: List[int]) -> int: | ||
| if len(nums) == 1: | ||
| return nums[0] | ||
|
|
||
| while True: | ||
| if nums[-1] < nums[0]: | ||
| nums[0] = nums.pop() | ||
| else: | ||
| break | ||
|
|
||
| return nums[0] | ||
|
|
||
| """ | ||
| class Solution: | ||
| def findMin(self, nums: List[int]) -> int: | ||
| return min(nums) | ||
| """ |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 스택을 이용한 레벨별 방문으로 깊이를 측정한다. 노드 하나씩만 방문하므로 선형 시간과 스택 공간이 필요하다. 개선 제안: 재귀 DFS나 단일 스택으로도 구현 가능하며, 초기 예외 처리와 반복 종료 조건을 명확히 정리하면 가독성이 좋아진다.
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. 1번 답안 level order search 방식으로 하신거 같은데 deque 쓰시면 하나만 쓰셔도 구현 가능하세요!
Contributor
Author
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. 코멘트보고 다시 풀어봤는데, 하나만 있어도 되네요 from collections import deque
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
que = deque()
if root is None:
return 0
que.append([root, 1])
while len(que) > 0 :
node, count = que.popleft()
if node.left is not None:
que.append([node.left, count+1])
if node.right is not None:
que.append([node.right, count+1])
return count |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # 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: | ||
| count = 0 | ||
| stacks1 = [root] | ||
| stacks2= [] | ||
|
|
||
| if root is None: | ||
| return count | ||
| while len(stacks1) > 0 : | ||
| count += 1 | ||
| while len(stacks1) > 0 : | ||
| node = stacks1.pop() | ||
|
|
||
| if node.left is not None: | ||
| stacks2.append(node.left) | ||
| if node.right is not None: | ||
| stacks2.append(node.right) | ||
| stacks1.extend(stacks2) | ||
| stacks2 = [] | ||
| return count | ||
|
|
||
| """ | ||
| class Solution: | ||
| def maxDepth(self, root: Optional[TreeNode]) -> int: | ||
| def depth(node, dep): | ||
| if (node.left is None) and (node.right is None): | ||
| return dep | ||
| if (node.left is not None) and (node.right is None): | ||
| return depth(node.left, dep+1) | ||
| if (node.left is None) and (node.right is not None): | ||
| return depth(node.right, dep+1) | ||
| else: | ||
| return max(depth(node.left, dep+1), depth(node.right, dep+1)) | ||
| if root is None: | ||
| return 0 | ||
| return depth(root, 1) | ||
| """ |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 새 노드를 매번 생성하는 방식으로 단순하지만, 원래 리스트의 노드를 재활용하면 추가 공간을 줄일 수 있다. 개선 제안: 가능하면 기존 노드를 재링크하여 메모리 재활용을 통해 추가 공간을 줄이는 방향을 고려해 보자.
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. 이 문제는 노드를 다시 만들 필요 없이 재활용이 가능한 문제라 꼭 해보시면 좋을것 같네요
Contributor
Author
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. 단순히 # 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]:
# Space: O(N)
# Time: O(N)
dummy = ListNode(val=0, next=None)
pointer = dummy
while (list1 is not None) and (list2 is not None):
if list1.val <= list2.val:
pointer.next = list1
list1 = list1.next
else:
pointer.next = list2
list2 = list2.next
pointer = pointer.next
if list1 is not None:
pointer.next = list1
elif list2 is not None:
pointer.next = list2
return dummy.next |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # 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]: | ||
| # Space: O(N) | ||
| # Time: O(N) | ||
| dummy = ListNode(val=0, next=None) | ||
| pointer = dummy | ||
| while (list1 is not None) and (list2 is not None): | ||
| if list1.val <= list2.val: | ||
| pointer.next = ListNode(list1.val) | ||
| list1 = list1.next | ||
| else: | ||
| pointer.next = ListNode(list2.val) | ||
| list2 = list2.next | ||
| pointer = pointer.next | ||
| if list1 is not None: | ||
| pointer.next = list1 | ||
| elif list2 is not None: | ||
| pointer.next = list2 | ||
|
|
||
| return dummy.next |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 현재 구현은 각 글자 위치를 추적하고 가능한 경로를 확장하는 방식으로 동작한다. 비효율적인 경우가 있어 최악의 경우 성능이 떨어질 수 있다. 개선 제안: 백트래킹으로 중복 방문을 방지하고, 방문 표시를 보존하면서 재귀적 DFS를 사용하는 것이 일반적이다. 또한 보드 크기와 단어 길이에 따른 최적화도 고려하자.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| from collections import defaultdict | ||
| class Solution: | ||
| def exist(self, board: List[List[str]], word: str) -> bool: | ||
| pos = defaultdict(list) | ||
| for i in range(len(board)): | ||
| for j in range(len(board[0])): | ||
| if board[i][j] in word: | ||
| tmp = pos.get(board[i][j], []) | ||
| tmp.append([i, j]) | ||
| pos[board[i][j]] = tmp | ||
|
|
||
| paths = pos.get(word[0], []) | ||
| paths = [[path] for path in paths] | ||
|
Comment on lines
+4
to
+13
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. 문자별 좌표를 미리 모아두는 흐름이 이해하기 좋았습니다! 저도 나중에 이렇게 접근해야겠어요 ㅎㅎ 이렇게 바꾸면 조회 성능이 더 좋아질 것 같아요!
Contributor
Author
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. 오오.. dict() 내부에 Runtime: 9700 ms -> 5667 ms from collections import defaultdict
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
pos = defaultdict(set)
for i in range(len(board)):
for j in range(len(board[0])):
if board[i][j] in word:
tmp = pos.get(board[i][j], set())
tmp.add((i, j))
pos[board[i][j]] = tmp
paths = pos.get(word[0], [])
paths = [[path] for path in paths]
for w in word[1:]:
temp = []
while len(paths) > 0:
path = paths.pop()
i , j = path[-1]
if ((i, j+1) in pos[w]) and ((i, j+1) not in path):
temp.append(path[:] + [(i, j+1)])
if ((i, j-1) in pos[w]) and ((i, j-1) not in path):
temp.append(path[:] + [(i, j-1)])
if ((i+1, j) in pos[w]) and ((i+1, j) not in path):
temp.append(path[:] + [(i+1, j)])
if ((i-1, j) in pos[w]) and ((i-1, j) not in path):
temp.append(path[:] + [(i-1, j)])
paths.extend(temp)
for path in paths:
if len(path) == len(word):
print(path)
return True
return False |
||
|
|
||
| for w in word[1:]: | ||
| temp = [] | ||
|
|
||
| while len(paths) > 0: | ||
| path = paths.pop() | ||
| i , j = path[-1] | ||
| if ([i, j+1] in pos[w]) and ([i, j+1] not in path): | ||
| temp.append(path[:] + [[i, j+1]]) | ||
| if ([i, j-1] in pos[w]) and ([i, j-1] not in path): | ||
| temp.append(path[:] + [[i, j-1]]) | ||
| if ([i+1, j] in pos[w]) and ([i+1, j] not in path): | ||
| temp.append(path[:] + [[i+1, j]]) | ||
| if ([i-1, j] in pos[w]) and ([i-1, j] not in path): | ||
| temp.append(path[:] + [[i-1, j]]) | ||
| paths.extend(temp) | ||
| for path in paths: | ||
| if len(path) == len(word): | ||
| return True | ||
| return False | ||
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.
🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 입력 배열의 회전 여부를 판단한 뒤 최소값을 찾는 간단한 구현이지만, 최악의 경우 전체 원소를 확인하므로 시간 복잡도는 선형이다.
개선 제안: 이진탐색으로 회전점을 이용해 O(log n) 시간으로 최솟값을 찾으면 더 효율적이다. 불필요한 pop/assignment 대신 인덱스 범위를 관리해 구현하는 편이 좋다.
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.
You must write an algorithm that runs in O(log n) time.이 문제는 Log N 시간복잡도로 답을 제한하고 있기 때문에 꼭 이진탐색으로 한번 시도해 보시길 바래요
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.
헉 그렇군요.
O(N)으로 풀어서 나름 뿌듯했는데 더 개선할 수 있었군요!개선해봤습니다!