일지이기 때문에 일기의 성격이 더 강합니다.

마지막 알고리즘 시간. 각 방법론에 대해서는 정리해둔 포스팅이 있으므로 여기를 참조.
https://bbbbabbbababababa.tistory.com/115
[Java 풀스택 개발자] 알고리즘 편#2: 알고리즘 방법론
0. 들어가기 전에지난 시간에 예고했던 알고리즘 파트2. 이번에는 알고리즘의 설계와 방법론에 대해서 다룰 예정이다. 지난번까지만 해도 다룰 수 있는 내용이 팍팍 바뀌어서 한 파트만 다루기
bbbbabbbababababa.tistory.com
여기서는 이론이 아니라 코드 관련한 내용만 다룬다.
DFS
DFS는 거의 재귀와 함께한다고 보면 좋은데, 재귀 문제에 대해서는 이미 몇 차례 다룬 적이 있다.
대표적인 것이 바로 블록 제거 게임.그리고 등산로이다.
https://bbbbabbbababababa.tistory.com/112
[코딩 테스트 RUN] SWEA 수업 : 25052. 등산로
⚠️ 주의!SWEA에서 낸 코딩 문제에 대한 해답이 들어있습니다.열람 시 주의해주세요. [SW Expret Academy] 25052. 등산로 SW Expert AcademySW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인
bbbbabbbababababa.tistory.com
https://bbbbabbbababababa.tistory.com/104
[코딩 테스트 RUN] SWEA RUN : 26071. 블록 제거 게임
⚠️ 주의!SWEA에서 낸 코딩 문제에 대한 해답이 들어있습니다.열람 시 주의해주세요. 강사님이 추천해주신 문제인데 재귀를 쓰지 않으면 답이 안 나오는 문제다.재귀는 정말 많이 어려운데 덕분
bbbbabbbababababa.tistory.com
DFS 및 재귀에 대해서는 많이 했는데, 말한 것처럼 순열에 대한 코드와 재귀 코드만 정리하겠다.
실제로 순열 자체는 자주 사용되지는 않는다. DFS 기본 베이스에 가까운 존재라고 생각하면 좋다.
반복 O 순열
//반복 O 순열
static int[] arr = {1,2,3}; // 사용할 숫자
static int[] result = new int[2]; // 뽑을 개수
static void perm(int depth) {
// 종료 조건
if (depth == result.length) {
for(int x : result) {
System.out.print(x + " ");
} return;
}
// 반복문 + 재귀
for(int i = 0; i < arr.length; i++) {
result[depth] = arr[i];
perm(depth + 1); // 다음 자리
}
}
public static void main(String[] args) {
perm(0);
}
반복 X 순열
//반복 X 순열
static int[] arr = {1,2,3};
static int[] result = new int[2];
static boolean[] visited = new boolean[3]; // 방문체크
static void perm(int depth) {
// 종료조건
if(depth == result.length) {
for(int x : result) {
System.out.print(x + " ");
} return;
}
// 반복문 + 재귀
for(int i = 0; i < arr.length; i++) {
if(visited[i]) continue; // 이미 사용한 숫자
visited[i] = true;
result[depth] = arr[i];
perm(depth + 1);
visited[i] = false; // 백트래킹
}
}
public static void main(String[] args) {
perm(0);
}
DFS 재귀
static boolean[] visited = new boolean[5];
static int[][] adj = {
{}, // 0번 노드
{2, 3}, // 1번과 연결된 노드
{1, 4}, // 2번
{1, 4}, // 3번
{2, 3} // 4번
};
public static void dfs(int u) {
// 1. 현재 노드 방문 처리
visited[u] = true;
System.out.print(u + " ");
// 2. 인접 노드 탐색
for (int v : adj[u]) {
if (!visited[v]) {
dfs(v); // 재귀 호출
}
}
}
BFS
BFS는 주로 큐를 이용한다. 최단거리 찾기에 사용함에 유의.
static int[] dist = new int[5];
static int[][] adj = {
{}, // 0번 노드
{2, 3}, // 1번과 연결된 노드
{1, 4}, // 2번
{1, 4}, // 3번
{2, 3} // 4번
};
public static void bfs(int s) {
Queue<Integer> q = new ArrayDeque<>();
q.offer(s); // 시작 정점을 큐에 삽입
dist[s] = 0; // 시작 정점의 거리는 0
while (!q.isEmpty()) {
int u = q.poll(); // 큐의 맨 앞 정점 꺼내기
for (int v : adj[u]) {
if (dist[v] == -1) { // 미방문
dist[v] = dist[u] + 1;
q.offer(v); // 큐에 삽입하여 이후 탐색
}
}
}
}
MST
모든 정점을 가장 적은 비용으로 이용하는 방법이다.(Greedy라고 생각하면 편하다)
소개 받은건 크루스칼과 프림이 있다. 그런데 추가로 다익스트라라는 존재도 있으니(이건 MST는 아니고 그리디의 한 종류이다.) 그 부분에 대해서도 이야기한다.
프림Prim 알고리즘
모든 정점을 잇는 최소 총합을 찾는 방법론이다. 모든 정점을 어떻게든 다 잇되, 사용한 간선들의 총합이 최소가 되게 하는 게 목적. 우선순위 큐를 자주 사용한다하는데… 나는 우선순위 큐와 친하지 않다. 큰일남…
핵심이 되는 한줄 로직은 이러하다. dist[v] = min(dist[v], weight)
public static void prim(int start) {
pq.offer(new Edge(start, 0));
while (!pq.isEmpty()) {
Edge cur = pq.poll(); // 최소 가중치 선택
int u = cur.node;
if (visited[u]) continue; // 중복 방문 방지
visited[u] = true;
total += cur.weight;
for (Edge next : adj[u]) {
if (!visited[next.node]) {
pq.offer(next);
}
}
}
}
KRUSKAL
간선 중심의 그리디 전략을 사용한다. 정점 중심인 프림과는 기준이 다르다고 할 수 있다. 정렬과 서로소 집합을 사용한다.
중요한 부분은 간선을 미리 오름차순 정렬을 해둔다는 것.
핵심이 되는 한줄 로직은 이러하다. if (find(u) != find(v)) union(u, v)
//1. 간선 정렬 (가중치 기준 오름차순)
Arrays.sort(edges);
for (Edge e : edges) {
// 2. 부모 확인 (Cycle 감지)
if (find(e.u) != find(e.v)) {
union(e.u, e.v); // 3. 집합 합치기
cost += e.weight;
}
}
//경로 압축 (Path Compression) 최적화
int find(int x) {
if (parent[x] == x) {
return x;
}
return parent[x] = find(parent[x]);
}
다익스트라Dijkstra
프림처럼 정점 중시이지만, 우선순위 큐가 필수이다. 시작점에서 각 정점까지의 최단 경로 찾는 것이 다익스트라의 중심이라고 할 수 있다.
핵심이 되는 한줄 로직은 이러하다. dist[v] = min(dist[v], dist[u] + weight)
// 1. 거리 장부 초기화
Arrays.fill(dist, INF);
dist[start] = 0;
// 2. 가방(PQ)에 시작점 넣기 {현재노드, 누적거리}
pq.offer(new int[]{start, 0});
while (!pq.isEmpty()) {
// 3. 가장 싼(가까운) 녀석 꺼내기
int[] curr = pq.poll();
int u = curr[0];
int d = curr[1];
// 4. [중요] 이미 더 짧은 길을 알면 무시 (방문체크 대신)
if (d > dist[u]) continue;
// 5. 이웃집 찔러보기 (Relaxation)
for (Edge next : adj[u]) {
// [핵심 로직] 지금까지 온 거리(d) + 다음 칸 비용 < 기존 기록
if (dist[next.v] > d + next.weight) {
dist[next.v] = d + next.weight; // 장부 갱신
pq.offer(new int[]{next.v, dist[next.v]}); // 다시 가방에 넣기
}
}
}'부트캠프 일지 > Java 풀스택 과정 강의' 카테고리의 다른 글
| [Java 풀스택 과정 강의] 3월 13일 (0) | 2026.03.14 |
|---|---|
| [Java 풀스택 과정 강의] 3월 12일 (0) | 2026.03.14 |
| [Java 풀스택 과정 강의] 3월 10일 (0) | 2026.03.14 |
| [Java 풀스택 과정 강의] 3월 9일 (0) | 2026.03.09 |
| [Java 풀스택 과정 강의] 3월 6일 (0) | 2026.03.09 |