Skip to content

Commit 4e7bf4e

Browse files
authored
Merge branch 'DaleStudy:main' into main
2 parents 11b4de6 + 1d173f8 commit 4e7bf4e

File tree

95 files changed

+4283
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+4283
-0
lines changed

clone-graph/taurus09318976.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""
2+
문제의 핵심 포인트:
3+
각 노드는 값과 이웃 노드들의 리스트를 가짐
4+
원본 그래프와 완전히 독립적인 새로운 그래프 생성
5+
모든 연결 관계를 그대로 복사
6+
7+
해결 방법:
8+
DFS(깊이 우선 탐색) + 해시맵을 사용함:
9+
해시맵으로 원본 노드와 복사본 노드의 매핑 관계 저장
10+
DFS로 그래프를 순회하면서 각 노드를 복사
11+
이미 복사된 노드는 해시맵에서 찾아서 재사용
12+
13+
Example 1의 경우
14+
1 --- 2
15+
| |
16+
| |
17+
4 --- 3
18+
19+
실행 과정:
20+
노드 1 복사: clone_1 생성, visited = clone_1
21+
노드 1의 이웃 2 복사: clone_2 생성, visited = clone_2
22+
노드 2의 이웃 1 처리: 이미 visited에 있으므로 clone_1 반환
23+
노드 2의 이웃 3 복사: clone_3 생성, visited = clone_3
24+
노드 3의 이웃들 처리: clone_2, clone_4 연결
25+
노드 1의 이웃 4 복사: clone_4 생성, visited = clone_4
26+
모든 연결 관계 완성
27+
Output: 원본과 동일한 구조의 완전히 새로운 그래프
28+
29+
시간 복잡도: O(V + E)
30+
V: 노드(정점)의 개수, E: 간선의 개수
31+
각 노드를 한 번씩 방문하고, 각 간선을 한 번씩 처리
32+
DFS의 표준 시간 복잡도
33+
34+
공간 복잡도: O(V)
35+
visited 해시맵이 모든 노드를 저장: O(V)
36+
DFS 재귀 호출 스택의 최대 깊이: O(V)
37+
복사된 그래프 자체도 O(V + E)의 공간 필요
38+
"""
39+
40+
from typing import Optional
41+
class Solution:
42+
def cloneGraph(self, node: Optional['Node']) -> Optional['Node']:
43+
# 빈 그래프인 경우 None 반환
44+
if not node:
45+
return None
46+
47+
# 원본 노드를 키로, 복사본 노드를 값으로 하는 해시맵 생성
48+
# 중복 복사를 방지하고 순환 참조 문제 해결
49+
visited = {}
50+
51+
# DFS 함수 정의
52+
def dfs(original_node):
53+
# 이미 복사된 노드라면 기존 복사본을 반환 (중복 복사 방지)
54+
if original_node in visited:
55+
return visited[original_node]
56+
57+
# 원본 노드의 값으로 새로운 노드 생성
58+
# 이웃 리스트는 빈 리스트로 초기화
59+
clone_node = Node(original_node.val, [])
60+
61+
# 해시맵에 원본-복사본 매핑 관계 저장
62+
# 순환 참조 방지를 위해 이웃을 처리하기 전에 먼저 저장
63+
visited[original_node] = clone_node
64+
65+
# 원본 노드의 모든 이웃들을 재귀적으로 복사
66+
# 복사된 이웃 노드들을 현재 복사본의 이웃 리스트에 추가
67+
for neighbor in original_node.neighbors:
68+
# 이웃 노드를 복사하고 현재 노드의 이웃 리스트에 추가
69+
clone_node.neighbors.append(dfs(neighbor))
70+
71+
# 완성된 복사본 노드 반환
72+
return clone_node
73+
74+
# 주어진 노드부터 DFS 시작
75+
return dfs(node)
76+
77+
78+
79+

course-schedule/HoonDongKang.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* [Problem]: [207] Course Schedule
3+
* (https://leetcode.com/problems/course-schedule/description/)
4+
*/
5+
6+
function canFinish(numCourses: number, prerequisites: number[][]): boolean {
7+
// 시간복잡도 O(n+m)
8+
// 공간복잡도 O(n+m)
9+
function graphFunc(numCourses: number, prerequisites: number[][]): boolean {
10+
const graph: number[][] = Array.from({ length: numCourses }, () => []);
11+
12+
for (const [course, prerequisite] of prerequisites) {
13+
graph[prerequisite].push(course);
14+
}
15+
16+
let traversing = new Array(numCourses).fill(false);
17+
let visited = new Array(numCourses).fill(false);
18+
19+
function dfs(course: number): boolean {
20+
if (traversing[course]) return false;
21+
if (visited[course]) return true;
22+
23+
traversing[course] = true;
24+
for (let pre of graph[course]) {
25+
if (!dfs(pre)) {
26+
return false;
27+
}
28+
}
29+
30+
traversing[course] = false;
31+
visited[course] = true;
32+
return true;
33+
}
34+
35+
for (let i = 0; i < numCourses; i++) {
36+
if (!visited[i] && !dfs(i)) {
37+
return false;
38+
}
39+
}
40+
return true;
41+
}
42+
}

course-schedule/Jeehay28.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// TC: O(V + E), V = numCourses, E = prerequisites.length
2+
// SC: O(V + E)
3+
4+
function canFinish(numCourses: number, prerequisites: number[][]): boolean {
5+
// 0: [1]
6+
// 1: []
7+
8+
const graph = new Map<number, number[]>();
9+
10+
// Initialize all courses
11+
for (let i = 0; i < numCourses; i++) {
12+
graph.set(i, []);
13+
}
14+
15+
// Build the graph
16+
for (const [crs, pre] of prerequisites) {
17+
graph.get(crs)!.push(pre);
18+
}
19+
20+
const traversing = new Set<number>();
21+
const finished = new Set<number>();
22+
23+
const dfs = (crs: number): boolean => {
24+
if (traversing.has(crs)) return false; // cycle detected
25+
26+
if (finished.has(crs)) return true; // already visited
27+
28+
traversing.add(crs);
29+
30+
for (const pre of graph.get(crs)!) {
31+
if (!dfs(pre)) return false;
32+
}
33+
34+
traversing.delete(crs);
35+
finished.add(crs);
36+
37+
return true;
38+
};
39+
40+
for (const crs of graph.keys()) {
41+
if (!dfs(crs)) return false;
42+
}
43+
44+
return true;
45+
}
46+

course-schedule/PDKhan.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//DFS
2+
class Solution {
3+
public:
4+
bool dfs(int curr, vector<vector<int>>& graph, vector<int>& visited){
5+
if(visited[curr] == 1)
6+
return false;
7+
8+
if(visited[curr] == 2)
9+
return true;
10+
11+
visited[curr] = 1;
12+
13+
for(int i = 0; i < graph[curr].size(); i++){
14+
if(dfs(graph[curr][i], graph, visited) == false)
15+
return false;
16+
}
17+
18+
visited[curr] = 2;
19+
20+
return true;
21+
}
22+
23+
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
24+
vector<vector<int>> graph (numCourses);
25+
vector<int> visited (numCourses, 0);
26+
27+
for(int i = 0; i < prerequisites.size(); i++){
28+
int course = prerequisites[i][0];
29+
int pre = prerequisites[i][1];
30+
31+
graph[pre].push_back(course);
32+
}
33+
34+
for(int i = 0; i < numCourses; i++){
35+
if(dfs(i, graph, visited) == false)
36+
return false;
37+
}
38+
39+
return true;
40+
}
41+
};
42+
43+
// BFS
44+
class Solution {
45+
public:
46+
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
47+
vector<vector<int>> graph (numCourses);
48+
vector<int> inDegree (numCourses, 0);
49+
50+
for(int i = 0; i < prerequisites.size(); i++){
51+
int course = prerequisites[i][0];
52+
int pre = prerequisites[i][1];
53+
54+
graph[pre].push_back(course);
55+
inDegree[course]++;
56+
}
57+
58+
queue<int> q;
59+
60+
for(int i = 0; i < numCourses; i++){
61+
if(inDegree[i] == 0)
62+
q.push(i);
63+
}
64+
65+
int count = 0;
66+
67+
while(!q.empty()){
68+
int curr = q.front();
69+
q.pop();
70+
count++;
71+
72+
for(int i = 0; i < graph[curr].size(); i++){
73+
if(--inDegree[graph[curr][i]] == 0)
74+
q.push(graph[curr][i]);
75+
}
76+
}
77+
78+
return count == numCourses;;
79+
}
80+
};

course-schedule/Tessa1217.java

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import java.util.ArrayList;
2+
import java.util.LinkedList;
3+
import java.util.List;
4+
import java.util.Queue;
5+
6+
class Solution {
7+
public boolean canFinish(int numCourses, int[][] prerequisites) {
8+
// return BFS(numCourses, prerequisites);
9+
return DFS(numCourses, prerequisites);
10+
}
11+
12+
// BFS 방식으로 풀이
13+
private boolean BFS(int numCourses, int[][] prerequisites) {
14+
15+
// 연결 그래프 생성
16+
List<List<Integer>> graph = new ArrayList<>();
17+
for (int i = 0; i < numCourses; i++) {
18+
graph.add(new ArrayList<>());
19+
}
20+
21+
// 들어오는 간선의 수 배열
22+
int[] inDegree = new int[numCourses];
23+
24+
for (int[] pre : prerequisites) {
25+
int course = pre[0];
26+
int prereq = pre[1];
27+
inDegree[course]++;
28+
graph.get(prereq).add(course);
29+
}
30+
31+
// 들어오는 간선이 없는 과목 Queue에 삽입
32+
Queue<Integer> q = new LinkedList<>();
33+
for (int i = 0; i < inDegree.length; i++) {
34+
if (inDegree[i] == 0) {
35+
q.offer(i);
36+
}
37+
}
38+
39+
// 들은 과목 수
40+
int takeCourse = 0;
41+
while (!q.isEmpty()) {
42+
int course = q.poll();
43+
takeCourse++;
44+
45+
for (int connect : graph.get(course)) {
46+
inDegree[connect]--;
47+
if (inDegree[connect] == 0) {
48+
q.offer(connect);
49+
}
50+
}
51+
}
52+
53+
return takeCourse == numCourses;
54+
}
55+
56+
// DFS 방식 풀이
57+
private boolean DFS(int numCourses, int[][] prerequisites) {
58+
List<List<Integer>> graph = new ArrayList<>();
59+
for (int i = 0; i < numCourses; i++) {
60+
graph.add(new ArrayList<>());
61+
}
62+
63+
for (int[] pre : prerequisites) {
64+
int course = pre[0];
65+
int prereq = pre[1];
66+
graph.get(prereq).add(course);
67+
}
68+
69+
// 처리 상태 배열
70+
int[] state = new int[numCourses];
71+
72+
for (int i = 0; i < numCourses; i++) {
73+
if (hasCycle(graph, state, i)) {
74+
return false;
75+
}
76+
}
77+
78+
return true;
79+
}
80+
81+
// 사이클 여부 확인
82+
private boolean hasCycle(List<List<Integer>> graph, int[] state, int course) {
83+
84+
if (state[course] == 1) return true; // 사이클이 있다면
85+
if (state[course] == 2) return false; // 이미 처리 완료되었으므로 return
86+
87+
state[course] = 1;
88+
for (int connect : graph.get(course)) {
89+
if (hasCycle(graph, state, connect)) {
90+
return true;
91+
}
92+
}
93+
state[course] = 2; // 처리 완료
94+
return false;
95+
}
96+
}
97+

course-schedule/ayosecu.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from typing import List
2+
from collections import defaultdict, deque
3+
4+
class Solution:
5+
"""
6+
- Time Complexity: O(N + P), N = numCourses, P = len(prerequisites)
7+
- Space Complexity: O(N + P)
8+
"""
9+
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
10+
# Topology Sort
11+
# BFS based, ingress count, visited
12+
ingress_cnt = [0] * numCourses
13+
dic = defaultdict(list)
14+
15+
for dst, src in prerequisites:
16+
ingress_cnt[dst] += 1
17+
dic[src].append(dst)
18+
19+
dq = deque([])
20+
for dst in range(numCourses):
21+
if ingress_cnt[dst] == 0:
22+
dq.append(dst)
23+
24+
visited_count = 0
25+
while dq:
26+
src = dq.popleft()
27+
visited_count += 1
28+
29+
for dst in dic[src]:
30+
ingress_cnt[dst] -= 1
31+
if ingress_cnt[dst] == 0:
32+
dq.append(dst)
33+
34+
return visited_count == numCourses
35+
36+
tc = [
37+
(2, [[1,0]], True),
38+
(2, [[1,0],[0,1]], False)
39+
]
40+
41+
sol = Solution()
42+
for i, (n, p, e) in enumerate(tc, 1):
43+
r = sol.canFinish(n, p)
44+
print(f"TC {i} is Passed!" if r == e else f"TC {i} is Failed! - Expected: {e}, Result: {r}")

0 commit comments

Comments
 (0)