diff --git a/course-schedule/HYUNAHKO.py b/course-schedule/HYUNAHKO.py new file mode 100644 index 000000000..e524f7972 --- /dev/null +++ b/course-schedule/HYUNAHKO.py @@ -0,0 +1,41 @@ +class Solution: + def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool: + # 1. 그래프 만들기 (인접 리스트) + # graph[A] = [B, C] : A를 듣기 위해 B, C가 필요함 (혹은 방향에 따라 반대) + graph = collections.defaultdict(list) + for course, pre in prerequisites: + graph[course].append(pre) + + # 2. 방문 상태 기록 (0, 1, 2) + # 0: 아직 안 가봄 (White) + # 1: 지금 탐색 중인 경로 (Grey) -> 여기서 또 만나면 뱅글뱅글 도는 것(사이클)! + # 2: 이미 검증 끝남 (Black) -> 안전함 + visit = [0] * numCourses + + def dfs(course): + # 탐색 중인 노드를 다시 만남 == 사이클 발생! + if visit[course] == 1: + return False + + # 이미 검증 끝난 노드 == 문제 없음 Pass + if visit[course] == 2: + return True + + # 현재 노드를 '탐색 중(1)'으로 표시 + visit[course] = 1 + + # 선수 과목들 쭉 파고들기 + for pre in graph[course]: + if not dfs(pre): # 재귀 호출 결과가 False(사이클 발견)라면 + return False # 즉시 False 리턴 + + # 더 이상 갈 곳 없음. '탐색 완료(2)'로 표시 + visit[course] = 2 + return True + + # 3. 모든 과목에 대해 확인 (그래프가 여러 덩어리일 수 있으므로) + for i in range(numCourses): + if not dfs(i): + return False + + return True diff --git a/invert-binary-tree/HYUNAHKO.py b/invert-binary-tree/HYUNAHKO.py new file mode 100644 index 000000000..cf4606241 --- /dev/null +++ b/invert-binary-tree/HYUNAHKO.py @@ -0,0 +1,17 @@ +# 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 invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: + if not root: + return None + + root.left, root.right = root.right, root.left + + self.invertTree(root.left) + self.invertTree(root.right) + + return root diff --git a/jump-game/HYUNAHKO.py b/jump-game/HYUNAHKO.py new file mode 100644 index 000000000..e094322fb --- /dev/null +++ b/jump-game/HYUNAHKO.py @@ -0,0 +1,15 @@ +class Solution: + def canJump(self, nums: List[int]) -> bool: + max_reachable = 0 + last_index = len(nums) - 1 + + for i, jump_len in enumerate(nums): + if i > max_reachable: + return False + + max_reachable = max(max_reachable, i + jump_len) + + if max_reachable >= last_index: + return True + + return True diff --git a/linked-list-cycle/HYUNAHKO.py b/linked-list-cycle/HYUNAHKO.py new file mode 100644 index 000000000..4f6d73a92 --- /dev/null +++ b/linked-list-cycle/HYUNAHKO.py @@ -0,0 +1,36 @@ +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, x): +# self.val = x +# self.next = None + +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + visited = set() + + current = head + while current: + if current in visited: + return True + + visited.add(current) + current = current.next + + return False + +# w/o set() +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + if not head or not head.next: + return False + + slow = head + fast = head.next + + while slow != fast: + if not fast or not fast.next: + return False + slow = slow.next + fast = fast.next.next + + return True diff --git a/longest-common-subsequence/HYUNAHKO.py b/longest-common-subsequence/HYUNAHKO.py new file mode 100644 index 000000000..c10475cf6 --- /dev/null +++ b/longest-common-subsequence/HYUNAHKO.py @@ -0,0 +1,17 @@ +class Solution: + def longestCommonSubsequence(self, text1: str, text2: str) -> int: + # Dynamic programming + n = len(text1) + m = len(text2) + + # text1 - col, text2 - row + dp= [[0] * (n+1) for _ in range(m+1)] + + for i in range(1, m+1): + for j in range(1, n+1): + if text2[i-1] == text1[j-1]: + dp[i][j] = dp[i-1][j-1] + 1 + else: + dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + + return dp[m][n] diff --git a/search-in-rotated-sorted-array/HYUNAHKO.py b/search-in-rotated-sorted-array/HYUNAHKO.py new file mode 100644 index 000000000..d594f057d --- /dev/null +++ b/search-in-rotated-sorted-array/HYUNAHKO.py @@ -0,0 +1,26 @@ +class Solution: + def search(self, nums: List[int], target: int) -> int: + left_index = 0 + right_index = len(nums) -1 + + while left_index <= right_index: + mid_index = (left_index + right_index) // 2 + + if nums[mid_index] == target: + return mid_index + + # 왼쪽 절반 정렬 확인 + if (nums[left_index] <= nums[mid_index]): + if (nums[left_index] <= target < nums[mid_index]): + right_index = mid_index -1 + else: + left_index = mid_index + 1 + + # 오른쪽 절반 정렬 확인 + else: + if (nums[mid_index] < target <= nums[right_index]): + left_index = mid_index + 1 + else: + right_index = mid_index -1 + + return -1