Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions find-minimum-in-rotated-sorted-array/daehyun99.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Binary Search, Two Pointers
  • 설명: 코드는 회전된 정렬 배열에서 최소값을 찾기 위해 양끝 비교와 요소 제거/교환으로 두 포인터의 위치를 좁히는 방식에 가깝습니다. 최적화 기법이나 패턴은 명확히 이 코드에서 두 포인터의 협력으로 구간을 좁히는 흐름으로 해석될 수 있습니다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n)
Space O(1)

피드백: 입력 배열의 회전 여부를 판단한 뒤 최소값을 찾는 간단한 구현이지만, 최악의 경우 전체 원소를 확인하므로 시간 복잡도는 선형이다.

개선 제안: 이진탐색으로 회전점을 이용해 O(log n) 시간으로 최솟값을 찾으면 더 효율적이다. 불필요한 pop/assignment 대신 인덱스 범위를 관리해 구현하는 편이 좋다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

Copy link
Copy Markdown
Contributor

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 시간복잡도로 답을 제한하고 있기 때문에 꼭 이진탐색으로 한번 시도해 보시길 바래요

Copy link
Copy Markdown
Contributor Author

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 시간복잡도로 답을 제한하고 있기 때문에 꼭 이진탐색으로 한번 시도해 보시길 바래요

헉 그렇군요. O(N)으로 풀어서 나름 뿌듯했는데 더 개선할 수 있었군요!
개선해봤습니다!

class Solution:
    def findMin(self, nums: List[int]) -> int:
        left_idx = 0
        mid_idx = len(nums)//2
        right_idx = len(nums)-1

        while True:
            if right_idx - left_idx <= 1:
                if nums[left_idx] <= nums[right_idx]:
                    return nums[left_idx]
                else:
                    return nums[right_idx]
            elif nums[mid_idx] > nums[right_idx]:
                left_idx = mid_idx
                mid_idx = (left_idx + right_idx) // 2
                right_idx = right_idx
            else:
                left_idx = left_idx
                right_idx = mid_idx
                mid_idx = (left_idx + right_idx) // 2

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)
"""
43 changes: 43 additions & 0 deletions maximum-depth-of-binary-tree/daehyun99.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Depth-First Search, Breadth-First Search, Binary Search
  • 설명: 코드가 트리의 최대 깊이를 구하기 위해 두 가지 방식으로 노드를 탐색하는데, 스택을 이용한 깊이 우선 탐색(while로 구성된 DFS)과 레벨 순서 탐색처럼 보이는 두 번째 구성은 BFS의 아이디어를 사용한다. 트리 순회와 깊이 계산의 패턴이 핵심이다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n)
Space O(n)

피드백: 스택을 이용한 레벨별 방문으로 깊이를 측정한다. 노드 하나씩만 방문하므로 선형 시간과 스택 공간이 필요하다.

개선 제안: 재귀 DFS나 단일 스택으로도 구현 가능하며, 초기 예외 처리와 반복 종료 조건을 명확히 정리하면 가독성이 좋아진다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1번 답안 level order search 방식으로 하신거 같은데 deque 쓰시면 하나만 쓰셔도 구현 가능하세요!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The 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)
"""
25 changes: 25 additions & 0 deletions merge-two-sorted-lists/daehyun99.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Two Pointers, Merge
  • 설명: 두 정렬 리스트를 하나로 합치는 과정에서 포인터를 이용해 두 리스트를 동시에 탐색하며 작은 값을 차례로 연결합니다. 순차적 병합과 포인터 이동으로 시간복잡도 O(n)로 해결하는 전형적인 패턴입니다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n + m)
Space O(1)

피드백: 새 노드를 매번 생성하는 방식으로 단순하지만, 원래 리스트의 노드를 재활용하면 추가 공간을 줄일 수 있다.

개선 제안: 가능하면 기존 노드를 재링크하여 메모리 재활용을 통해 추가 공간을 줄이는 방향을 고려해 보자.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 문제는 노드를 다시 만들 필요 없이 재활용이 가능한 문제라 꼭 해보시면 좋을것 같네요

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

단순히 ListNode(list2.val) 처럼 넣던 값을 list2로 바꾸면 해결이 되네요.
리뷰 감사합니다!

# 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
33 changes: 33 additions & 0 deletions word-search/daehyun99.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Depth-First Search, Breadth-First Search, Backtracking
  • 설명: word-search 문제에서 보드의 각 위치에서 단어의 각 글자를 탐색하는 방식이 DFS/BFS 혼합으로 구현되며, 경로를 추적하며 가능한 위치를 확장하는 방식이 Backtracking의 특징을 보입니다.

📊 시간/공간 복잡도 분석

복잡도
Time O(R * C * 4^L)
Space O(L)

피드백: 현재 구현은 각 글자 위치를 추적하고 가능한 경로를 확장하는 방식으로 동작한다. 비효율적인 경우가 있어 최악의 경우 성능이 떨어질 수 있다.

개선 제안: 백트래킹으로 중복 방문을 방지하고, 방문 표시를 보존하면서 재귀적 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

문자별 좌표를 미리 모아두는 흐름이 이해하기 좋았습니다! 저도 나중에 이렇게 접근해야겠어요 ㅎㅎ

pos = defaultdict(set)
pos[board[i][j]].add((i, j))

이렇게 바꾸면 조회 성능이 더 좋아질 것 같아요!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오오.. dict() 내부에 set을 쓸 생각은 못 했었는데 감사합니다.
풀어보니 확실히 성능이 좋아지긴 하네요!
리뷰 감사합니다!

Runtime: 9700 ms -> 5667 ms
Memory: 405 MB -> 371 MB

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
Loading