Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
99 changes: 99 additions & 0 deletions course-schedule/hi-rachel.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,102 @@ def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
queue.append(neighbor)

return completed == numCourses

"""
위상 정렬을 구하는 알고리즘
1. DFS 기반 (스택을 쌓아 뒤집는 방식)
2. Kahn 알고리즘 (진입차수 0부터 차례로 큐 처리)

Kahn 알고리즘이란?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

완전히 이해 못함, 나중에 복습 필요

Copy link
Contributor

Choose a reason for hiding this comment

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

그래프 문제는 Map, Dict를 사용해서 점과 점을 이어간다고 생각하시면 조금 이해하시는데 도움이 될수도 있을것 같아요!

방향 그래프에서 진입차수(indegree)가 0인 정점부터 차례로 제거(큐에 넣어 꺼내기)하며 위상 순서를 만드는 방법.
진입차수가 0인 정점이 하나도 없는데 아직 남은 정점이 있다면 사이클 존재 -> 위상 정렬 불가.

위상 순서: 방향 그래프에서 간선(u→v)이 있다면, 순서에서 u가 항상 v보다 앞에 나오는 정점들의 나열.
진입차수: 정점으로 들어오는 간선의 개수.


TC: O(V + E), V: 과목 수, E: prerequisite 관계 수
SC: O(V + E), 그래프 + 진입차수 배열
"""
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
# 1) 그래프(인접 리스트)와 진입차수 배열 만들기
adj = [[] for _ in range(numCourses)]
indeg = [0] * numCourses
for a, b in prerequisites: # b -> a (b를 먼저 들어야 a를 들을 수 있음)
adj[b].append(a)
indeg[a] += 1

# 2) 진입차수 0인 정점들로 큐 초기화
q = deque([i for i in range(numCourses) if indeg[i] == 0])
taken = 0 # 처리(수강) 완료한 과목 수

# 3) 큐에서 빼며 간선 제거(=후속 과목 진입차수 감소)
while q:
u = q.popleft()
taken += 1
for v in adj[u]:
indeg[v] -= 1
if indeg[v] == 0:
q.append(v)

# 4) 모두 처리됐으면 사이클 없음
return taken == numCourses


"""
DFS 기반
TC: O(V + E), V: 과목 수, E: prerequisite 관계 수
SC: O(V + E), 그래프 + 탐색 중인 과목 집합 + 수강 완료한 과목 집합
"""
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
graph = {i: [] for i in range(numCourses)}
for crs, pre in prerequisites:
# 선수 과목을 원소로 추가
graph[crs].append(pre)

# 탐색중
traversing = set()
# 수강가능한 과목
finished = set()

def can_finish(crs):
if crs in traversing:
return False
if crs in finished:
return True

traversing.add(crs)
for pre in graph[crs]:
if not can_finish(pre):
return False
traversing.remove(crs)
finished.add(crs)
return True

for crs in graph:
if not can_finish(crs):
return False
return True

# 줄인 코드
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
graph = {i: [] for i in range(numCourses)}
for crs, pre in prerequisites:
graph[crs].append(pre)

traversing = set()

@cache
def can_finish(crs):
if crs in traversing:
return False

traversing.add(crs)
result = all(can_finish(pre) for pre in graph[crs])
traversing.remove(crs)
return result

return all(can_finish(crs) for crs in graph)
25 changes: 21 additions & 4 deletions search-in-rotated-sorted-array/hi-rachel.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
"""
https://leetcode.com/problems/search-in-rotated-sorted-array/solutions/
문제: 회전된 오름차순 정렬된 배열 nums에서 target 값의 인덱스를 반환하라.
Idea: 이진 탐색 패턴 사용
- in → 리스트 전체를 선형 탐색 (O(N))
- index → 다시 처음부터 선형 탐색 (O(N))
TC: O(logN)
Brute Force
TC: O(N)
SC: O(1)
"""

from typing import List


class Solution:
def search(self, nums: List[int], target: int) -> int:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

아래 이분탐색 코드가 효율적

if target in nums:
return nums.index(target)
else:
return -1

"""
문제: 회전된 오름차순 정렬된 배열 nums에서 target 값의 인덱스를 반환하라.
Idea: 이진 탐색 패턴 사용
TC: O(logN), while 루프에서 매번 절반씩 줄
SC: O(1)
"""
class Solution:
def search(self, nums: List[int], target: int) -> int:
left, right = 0, len(nums) - 1
Expand Down