그래프
- 객체의 일부 쌍(Pair)들이 '연관되어' 있는 객체 집합 구조
오일러 경로
- 모든 간선을 한 번씩 방문하는 유한 그래프
해밀턴 경로
- 각 정점을 한 번씩 방문하는 무향 또는 유향 그래프 경로
- 최적 알고리즘이 없는 N-P 완전 문제
해밀턴 순환
- 해밀턴 경로 중에서 원래의 출발점으로 돌아오는 경로
외판원 문제(Travelling Salesman Problem)
- 한 번만 방문하여 출발지로 돌아오는 경로 중 가장 짧은 경로
그래프 순회(Graph Traversal)
- 그래프의 각 정점을 방문하는 과정
- 그래프를 인접 리스트로 표현한 예
- 인접 리스트는 출발 노드를 키로, 도착 노드를 값으로 표현
Map<Integer, List<Integer>> graph = new HashMap<>();
graph.put(1,Arrays.asList(2,3,4));
graph.put(1,Arrays.asList(5));
graph.put(1,Arrays.asList(5));
graph.put(1,Arrays.asList());
graph.put(1,Arrays.asList(6,7));
1) 깊이 우선 탐색(Depth-First Search)
- 스택 또는 재귀로 구현
재귀 구조로 구현
public List<Integer> recursiveDFS(int v, List<Integer> discovered) {
//현재 노드 저장(전위 순회)
discovered.add(v);
//주변 노드 반복
for(Integer w : graph.get(v)) {
//아직 처리되지 않은 노드라면 깊이 기반 탐색 진행
if(!discovered.contains(w)) {
discovered = recursiveDFS(w, discovered);
}
}
//모든 깊이를 탐색하면 리턴
return discovered;
스택을 이용한 반복 구조로 표현
- 스택을 이용해 모든 인접 간선을 추출하고 다시 도착점인 정점을 스택에 삽입하는 구조
public List<Integer> iterativeDFS(int v) {
//결과 노드를 저장할 리스트 선언
List<Integer> discovered = new ArrayList<>();
//스택 선언은 효율적인 ArrayDeque 자료형 선언
Deque<Integer> stack = new ArrayDeque<>();a
//현재 노드를 스택에 삽입
stack.push(v);
//스택이 모두 비워질 때까지 반복
while(!stack.isEmpty()) {
//스택에서 추출
v = stack.pop();
//이미 방문한 노드가 아니라면 방문 노드에 추가하고 주변 노드를 모두 스택에 삽입
if(!discovered.contains(v)) {
discovered.add(v);
//현재 노드에서 연결된 모든 주변 노드를 스택에 삽입
for(int w : graph.get(v)) {
stack.push(w)p;
}
}
}
//더 이상 탐색할 노드가 없으면 리턴
return discovered;
}
2) 너비 우선 탐색 (Breadth-First Search)
- 큐를 이용한 반복 구조로 구현
public List<Integer> iterativeBFS(int start_v) {
//결과 노드를 저장할 리스트 선언
List<Integer> discovered = new ArrayList<>();
//시작 노드 삽입
discovered.add(start_v);
//큐는 인터페이스이며 자료형 선언은 LinkedList 사용
Queue<Integer> queue = new LinkedList<>();
//시작 노드 삽입
queue.add(start_v);
//큐가 모두 비워질 때까지 반복
while(!queue.isEmpty()) {
//큐에서 추출
int v = queue.poll();
//현재 노드에서 연결된 모든 주변 노드를 큐에 삽입
for(int w : graph.get(v)) {
//이미 방문한 노드가 아니라면 방문 노드에 추가하고 주변 노드를 모두 큐에 삽입
if(!discovered.contains(w)) {
discovered.add(w);
queue.add(w);
}
}
}
//더 이상 탐색할 노드가 없으면 리턴
return discovered;
}
백트래킹(Backtracking)
- 해결책에 대한 후보를 구축해 나가다 가능성이 없다고 판단되는 즉시 후보를 포기(백트랙 Backtrack)해 정답을 찾아가는 범용적인 알고리즘으로, 제약 충족 문제(Constraint Satisfaction Problem)등에 유용하다.
- DFS와 같은 방식으로 탐색하는 모든 방법을 뜻하며, DFS는 백트래킹의 골격을 이루는 알고리즘이다.
- 백트래킹은 주로 재귀로 구현하며, 알고리즘마다 DFS 변형이 조금씩 일어나지만 기본적으로 모두 DFS의 범주에 속한다.
- 탐색할 필요가 없는 상태를 제외한다는 것인데, 이를 가지치기라고 한다.
제약 충족 문제(Constraint Satisfaction Problem,CSP)
- 수많은 제약 조건을 충족하는 상태를 찾아내는 수학 문제
ex) 스도쿠, 십자말풀이, 8퀸 문제, 4색 문제, 배낭문제, 문자열 파싱, 조합 최적화 등
'Java > 알고리즘' 카테고리의 다른 글
[자바 알고리즘 인터뷰] 12장 그래프 (2) 전화번호 문자 조합 (0) | 2024.05.16 |
---|---|
[자바 알고리즘 인터뷰] 12장 그래프 (1) 섬의 개수 (0) | 2024.05.16 |
[자바 알고리즘 인터뷰] ch 11 해시 테이블 (5) 완주하지 못한 선수 (0) | 2024.05.14 |
[자바 알고리즘 인터뷰] ch 11. 해시 테이블 (4) 상위 k빈도 엘리먼트 (0) | 2024.05.14 |
[자바 알고리즘 인터뷰] ch 11. 해시 테이블 (3) 중복 문자 없는 가장 긴 부분 문자열 (0) | 2024.05.13 |