Skip to content

Commit 5438731

Browse files
authored
Merge pull request #50 from codingTestStd/JooKangsan
Joo kangsan
2 parents 3bfce03 + da4b57f commit 5438731

12 files changed

+508
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* @param {number[][]} edges
3+
* @return {number}
4+
*/
5+
function findCenter(edges) {
6+
const [a, b] = edges[0];
7+
const [c, d] = edges[1];
8+
9+
return a === c || a === d ? a : b;
10+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* @param {number} n
3+
* @param {number[][]} edges
4+
* @param {number} source
5+
* @param {number} destination
6+
* @return {boolean}
7+
*/
8+
function validPath(n, edges, source, destination) {
9+
const graph = new Map();
10+
11+
for (let i = 0; i < n; i++) {
12+
graph.set(i, []);
13+
}
14+
15+
for (const [u, v] of edges) {
16+
graph.get(u).push(v);
17+
graph.get(v).push(u);
18+
}
19+
20+
const visited = new Array(n).fill(false);
21+
const queue = [source];
22+
visited[source] = true;
23+
24+
while (queue.length > 0) {
25+
const current = queue.shift();
26+
27+
if (current === destination) {
28+
return true;
29+
}
30+
31+
for (const neighbor of graph.get(current)) {
32+
if (!visited[neighbor]) {
33+
visited[neighbor] = true;
34+
queue.push(neighbor);
35+
}
36+
}
37+
}
38+
39+
return false;
40+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* @param {number} n
3+
* @param {number[][]} trust
4+
* @return {number}
5+
*/
6+
function findJudge(n, trust) {
7+
const trustScores = new Array(n + 1).fill(0);
8+
9+
for (const [a, b] of trust) {
10+
trustScores[a] -= 1;
11+
trustScores[b] += 1;
12+
}
13+
14+
for (let i = 1; i <= n; i++) {
15+
if (trustScores[i] === n - 1) {
16+
return i;
17+
}
18+
}
19+
20+
return -1;
21+
}

JooKangSan/[week7]Graph/Graph.md

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# 그래프 (Graph) 이론
2+
3+
## 1. 그래프의 정의
4+
- 정점(Vertex)과 간선(Edge)으로 구성된 데이터 구조
5+
- 객체 간의 관계를 표현하는 추상적 네트워크
6+
7+
## 3. 그래프의 종류
8+
### 3.1 방향성에 따른 분류
9+
1. 방향 그래프(Directed Graph)
10+
- 간선에 방향성 존재
11+
- 일방향 관계 표현
12+
13+
2. 무방향 그래프(Undirected Graph)
14+
- 간선에 방향성 없음
15+
- 양방향 관계 표현
16+
17+
### 3.2 연결성에 따른 분류
18+
1. 연결 그래프(Connected Graph)
19+
- 모든 정점이 서로 연결됨
20+
21+
2. 비연결 그래프(Disconnected Graph)
22+
- 일부 정점이 연결되지 않음
23+
24+
### 3.3 특수한 그래프
25+
- 트리(Tree)
26+
- 완전 그래프(Complete Graph)
27+
- 이분 그래프(Bipartite Graph)
28+
29+
## 4. 그래프 표현 방법
30+
### 4.1 인접 행렬(Adjacency Matrix)
31+
```javascript
32+
class GraphAdjacencyMatrix {
33+
constructor(vertices) {
34+
this.vertices = vertices;
35+
this.matrix = Array(vertices).fill().map(() => Array(vertices).fill(0));
36+
}
37+
38+
addEdge(v1, v2) {
39+
this.matrix[v1][v2] = 1;
40+
this.matrix[v2][v1] = 1; // 무방향 그래프의 경우
41+
}
42+
}
43+
```
44+
45+
### 4.2 인접 리스트(Adjacency List)
46+
```javascript
47+
class GraphAdjacencyList {
48+
constructor() {
49+
this.adjacencyList = {};
50+
}
51+
52+
addVertex(vertex) {
53+
if (!this.adjacencyList[vertex]) {
54+
this.adjacencyList[vertex] = [];
55+
}
56+
}
57+
58+
addEdge(vertex1, vertex2) {
59+
this.adjacencyList[vertex1].push(vertex2);
60+
this.adjacencyList[vertex2].push(vertex1); // 무방향 그래프
61+
}
62+
}
63+
```
64+
65+
## 5. 그래프 탐색 알고리즘
66+
### 5.1 깊이 우선 탐색 (DFS)
67+
```javascript
68+
function dfs(graph, startVertex) {
69+
const visited = new Set();
70+
71+
function explore(vertex) {
72+
visited.add(vertex);
73+
console.log(vertex);
74+
75+
for (let neighbor of graph.adjacencyList[vertex]) {
76+
if (!visited.has(neighbor)) {
77+
explore(neighbor);
78+
}
79+
}
80+
}
81+
82+
explore(startVertex);
83+
}
84+
```
85+
86+
### 5.2 너비 우선 탐색 (BFS)
87+
```javascript
88+
function bfs(graph, startVertex) {
89+
const visited = new Set();
90+
const queue = [startVertex];
91+
visited.add(startVertex);
92+
93+
while (queue.length > 0) {
94+
const currentVertex = queue.shift();
95+
console.log(currentVertex);
96+
97+
for (let neighbor of graph.adjacencyList[currentVertex]) {
98+
if (!visited.has(neighbor)) {
99+
visited.add(neighbor);
100+
queue.push(neighbor);
101+
}
102+
}
103+
}
104+
}
105+
```
106+
107+
## 6. 최단 경로 알고리즘
108+
### 6.1 다익스트라 알고리즘
109+
```javascript
110+
function dijkstra(graph, startVertex) {
111+
const distances = {};
112+
const previous = {};
113+
const pq = new PriorityQueue();
114+
115+
// 초기화 로직
116+
for (let vertex in graph.adjacencyList) {
117+
if (vertex === startVertex) {
118+
distances[vertex] = 0;
119+
pq.enqueue(vertex, 0);
120+
} else {
121+
distances[vertex] = Infinity;
122+
}
123+
previous[vertex] = null;
124+
}
125+
126+
// 최단 경로 탐색 로직
127+
while (!pq.isEmpty()) {
128+
let currentVertex = pq.dequeue().val;
129+
130+
for (let neighbor in graph.adjacencyList[currentVertex]) {
131+
// 거리 계산 및 업데이트 로직
132+
}
133+
}
134+
135+
return { distances, previous };
136+
}
137+
```
138+
139+
## 7. 그래프 문제 주의 사항
140+
1. 그래프 표현 방법 선택
141+
2. 적절한 탐색 알고리즘 적용
142+
3. 방문 체크로 무한 루프 방지
143+
4. 메모리 효율성 고려
144+
145+
## 8. 시간 복잡도
146+
- DFS/BFS: O(V + E)
147+
- 다익스트라: O((V + E)logV)
148+
- 플로이드-워셜: O(V³)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
function edgeScore(edges) {
2+
const n = edges.length;
3+
const scores = new Array(n).fill(0);
4+
5+
for (let i = 0; i < n; i++) {
6+
scores[edges[i]] += i;
7+
}
8+
9+
let maxScore = 0;
10+
let maxNode = 0;
11+
12+
for (let i = 0; i < n; i++) {
13+
if (scores[i] > maxScore) {
14+
maxScore = scores[i];
15+
maxNode = i;
16+
}
17+
}
18+
19+
return maxNode;
20+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
function solution(maps) {
2+
const n = maps.length;
3+
const m = maps[0].length;
4+
5+
const visited = Array.from(Array(n), () => Array(m).fill(false));
6+
7+
const dx = [-1, 1, 0, 0];
8+
const dy = [0, 0, -1, 1];
9+
10+
const queue = [[0, 0, 1]];
11+
visited[0][0] = true;
12+
13+
while (queue.length > 0) {
14+
const [x, y, count] = queue.shift();
15+
16+
if (x === n - 1 && y === m - 1) {
17+
return count;
18+
}
19+
20+
for (let i = 0; i < 4; i++) {
21+
const nx = x + dx[i];
22+
const ny = y + dy[i];
23+
24+
if (
25+
nx >= 0 && nx < n &&
26+
ny >= 0 && ny < m &&
27+
maps[nx][ny] === 1 &&
28+
!visited[nx][ny]
29+
) {
30+
visited[nx][ny] = true;
31+
queue.push([nx, ny, count + 1]);
32+
}
33+
}
34+
}
35+
36+
return -1;
37+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# 백트래킹 (Backtracking)
2+
3+
## 1. 백트래킹
4+
- 백트래킹은 모든 가능한 경우의 수를 탐색하는 알고리즘 기법
5+
- 문제 해결을 위해 모든 가능한 경우를 시도 후, 유망하지 않은 경우는 즉시 포기하는 방식
6+
- 깊이 우선 탐색(DFS)의 일종으로 볼 수 있음
7+
8+
## 2. 백트래킹의 핵심 특징
9+
1. 완전 탐색: 모든 가능한 경우의 수를 탐색
10+
2. 가지치기(Pruning)**: 불필요한 경로를 빠르게 제거
11+
3. 재귀적 접근: 문제를 작은 하위 문제로 분해
12+
4. 상태 되돌리기: 탐색 후 이전 상태로 복귀
13+
14+
## 3. 백트래킹 알고리즘의 일반적인 구조
15+
```javascript
16+
function backtrack(현재상태, 다른매개변수) {
17+
// 기저 조건: 문제의 해결책을 찾았을 때
18+
if (문제해결조건) {
19+
결과에 추가
20+
return
21+
}
22+
23+
// 현재 상태에서 가능한 모든 선택지 탐색
24+
for (각 선택지) {
25+
// 선택지 추가
26+
현재상태에 선택지 추가
27+
28+
// 재귀적 탐색
29+
backtrack(변경된상태)
30+
31+
// 백트래킹: 상태 되돌리기
32+
현재상태에서 선택지 제거
33+
}
34+
}
35+
```
36+
37+
## 4. 백트래킹의 대표적인 문제 유형
38+
1. **순열 생성**
39+
- 모든 가능한 순서 조합 찾기
40+
- 예: 숫자 배열의 모든 순열
41+
42+
2. **조합 생성**
43+
- 특정 길이의 조합 찾기
44+
- 예: n개 중 k개 선택
45+
3. **부분집합 생성**
46+
- 주어진 집합의 모든 부분집합 생성
47+
48+
4. **제약 조건 문제**
49+
- N-Queen 문제
50+
- 스도쿠 풀이
51+
- 괄호 생성
52+
53+
## 5. 백트래킹 vs 완전 탐색
54+
- **완전 탐색**: 모든 경우의 수를 무조건 탐색
55+
- **백트래킹**: 불필요한 경로를 효율적으로 제거
56+
57+
## 6. 시간 복잡도
58+
- 최악의 경우: O(2^n) 또는 O(n!)
59+
- 가지치기를 통해 실제 시간 복잡도는 줄어 들 수 있음
60+
61+
## 7. 주의사항
62+
- 재귀 깊이에 주의 (스택 오버플로우 위험)
63+
- 상태 되돌리기(백트래킹) 로직 명확히 구현
64+
- 문제의 특성에 맞는 가지치기 전략 필요
65+
- 메모리 사용에 유의
66+
- 기저 조건 정확히 설정
67+
68+
## 8. JavaScript 백트래킹 예제
69+
```javascript
70+
function solution(n, m) {
71+
// 순열을 계산하고자 하는 원소가 담긴 배열 [1, 2, 3, 4]
72+
let arr = Array.from({ length: n }, (v, i) => i + 1);
73+
// 각 원소의 인덱스 별 방문 여부
74+
let visited = new Array(n).fill(false);
75+
// 현재 순열에 포함된 원소
76+
let selected = [];
77+
78+
let answer = "";
79+
function dfs(arr, depth) {
80+
// 모든 순열을 확인하는 부분
81+
if (depth === m) {
82+
let result = []; // 순열 결과 저장
83+
for (let i of selected) result.push(arr[i]);
84+
for (let x of result) answer += x + " ";
85+
answer += "\n"; // 줄바꿈 처리
86+
return;
87+
}
88+
for (let i = 0; i < arr.length; i++) {
89+
if (visited[i]) continue; // 이미 처리된 원소라면 무시하고 넘어감
90+
selected.push(i); // 현재 원소 선택
91+
visited[i] = true; // 방문처리
92+
dfs(arr, depth + 1); // 재귀함수 호출
93+
selected.pop(); // 현재 원소 선택 취소
94+
visited[i] = false; // 원소 방문 처리 취소
95+
}
96+
}
97+
dfs(arr, 0);
98+
return answer;
99+
}
100+
101+
console.log(solution(4, 2));
102+
```

0 commit comments

Comments
 (0)