-
[ DFS / BFS ] 개념 및 예제 정리Java/코딩테스트 2023. 4. 5. 18:54
코딩테스트에서 자주 사용되는 완전 탐색 기법 DFS/BFS 정리
자주 나오기도 하고... 중요하기도 해서 복습겸 정리하는 포스팅!
DFS
🌷특징 및 언제 사용?
- 탐색 공간 자체는 크지만 깊이가 유한할 때(공간 복잡도가 작다)
- 최단 경로가 아니어도 괜찮을 때
- 재귀함수로 구현 -> 현재 검사하는 상태에서 전이할 수 있는 상태라면 해당 상태로 전이
- 시작하는 부분에서 한쪽 분기 정하고 최대 깊이까지 탐색 후 다른 분기로 이동, 다시 최대 깊이까지 탐색 ...
- 단절점 찾기, 단절선 찾기, 위상정렬, 사이클 찾기 등..
🌷기본 코드 구현 시 필요한 것
- 방문 여부를 저장할 방문 여부 배열
- 재귀함수로 구현하거나 스택 활용!
🌷 로직
1. while (스택에 값이 있는 동안)
2. 방문 여부 검사
3. state 변수(현재 방문한 변수)에 대한 처리(문제마다 다름)
4. 다음에 방문해야할 자료에 대해 범위, 방문 여부 등 문제에 따라 조건 검사
5. 조건에 위배되지 않으면 스택에 push or 재귀 함수 호출
boolean isVisited[] = new boolean[n]; Stack<Integer> stack = new Stack<>(); while (!stack.isEmpty()) { int state = stack.pop(); if (isVisited[]) { // continue 또는 리턴 } isVisted[state] = true; for (int next : getNext(state)) { if (!isVisted[next]) { stack.push(next); } } } // 재귀로 구현한다면 static void DFS(int node) { if (visited[node]) { return ; } // 이미 방문한 노드인 경우엔 수행 X visited[node] = true; // 한 번 지난 노드는 다시 안 지나가게끔 for (int i : graph[node]) { if (!visited[i]) { DFS(i); } } }
🌷프로그래머스 lv3 네트워크
https://school.programmers.co.kr/learn/courses/30/lessons/43162
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
DFS긴 DFS인데 처음에 구하려는 답을 내가 잘못 생각했다. 문제이해를 잘못했었는데, 제대로 이해해도 못풀어서 해설을 보고 코드를 짰다ㅎ...
여기서의 visited는 각 컴퓨터별로 연결된거 모두 탐색해봤는지를 저장하는 배열이다. 이 visited를 계속 DFS함수 매개변수로 넣어주고, 한 컴퓨터당 탐색이 끝나면 answer++해준다.
어려운 문젠 아닌거같은데 아직 부족하군...허허
import java.util.*; class Solution { public int solution(int n, int[][] computers) { boolean[] visited = new boolean[n]; int answer = 0; for (int i = 0; i < n; i++) { if (visited[i]) { continue; } DFS(i, computers, visited); answer++; } return answer; } void DFS(int now, int[][] computers, boolean[] visited) { Stack<Integer> stack = new Stack<>(); stack.push(now); while (!stack.isEmpty()) { int temp = stack.pop(); if (visited[temp]) { continue; } visited[temp] = true; for (int i = 0; i < computers[temp].length; i++) { if (computers[temp][i] == 0) { continue; } if (temp != i) { stack.push(i); } } } } }
BFS
🌷특징 및 언제 사용?
- 초기 상태에서 가까운 상태부터 탐색
- 최단 거리나 최단 시간 등 목표 상태에서 도달할 수 있는 가장 빠른 경로 탐색
- 탐색 공간의 깊이 제약이 없는 편이나 공간복잡도가 크다
- 큐를 사용, 큐가 탐색 공간을 나타내고 큐에 다음 탐색할 것들을 추가하는 방식으로 진행 ..
🌷DFS와 차이점?
- 스택 대신 큐를 사용
- 큐에 넣어줄 때 방문 처리를 한다는 점
boolean[] isVisited = new boolean[n]; Queue<Integer>() queue = new LinkedList<>(); queue.add(0); //초기 상태 저장 isVisited[0] = true; while (!queue.isEmpty()) { int now = queue.poll(); for (int next : getNextStates(now)) { // 방문 여부 외에 추가할만한 검사 조건들 추가하기 if (isVisted[next]) { continue; } } isVisited[next] = true; queue.add(next); } static void BFS(int num) { Queue<Integer> queue = new LinkedList<Integer>(); queue.add(num); isVisited[num] = true; while(!queue.isEmpty()) { int now = queue.poll(); System.out.print(now + " "); for (int i : graph[now]) { if (!isVisited[i]) { isVisited[i] = true; queue.add(i); } } } }
🌷프로그래머스 level3 단어변환
https://school.programmers.co.kr/learn/courses/30/lessons/43163
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
🌷로직
- 하나의 문자만 다른지 검사(word1 -> word2 바꿀 수 있는지 여부 검사하는 함수)
-> boolean canChange(String word1, String word2)
- 바꿀 수 있는 단어들을 다 큐에 넣어두고 탐색 수행 (BFS)
- 큐에서 꺼낼 때마다 target과 같은 문자열인지 확인, 맞다면 답 리턴
- 큐가 다 비었는데도 리턴되지 않았다 => 전환이 불가능하다는 뜻이므로 0 리턴
import java.util.*; class Solution { public int solution(String begin, String target, String[] words) { Queue<Word> queue = new LinkedList<>(); boolean[] visited = new boolean[words.length]; queue.add(new Word(begin, 0)); while (!queue.isEmpty()) { Word w = queue.poll(); if (w.st.equals(target)) { return w.count; // 꺼냈는데 target과 같다면 답 리턴 } for (int i = 0; i < words.length; i++) { if (!visited[i]) { if (canChange(w.st, words[i])) { visited[i] = true; queue.add(new Word(words[i], w.count+1)); } } } } return 0; // 다 돌아도 답 안나오는 경우 } public boolean canChange(String word1, String word2) { int count = 0; char[] first = word1.toCharArray(); char[] second = word2.toCharArray(); for (int i = 0; i < word1.length(); i++) { if (first[i] != second[i]) { count++; } if (count > 1) { return false; } } return true; } class Word { String st; int count; public Word(String s, int c) { this.st = s; this.count = c; } } }
'Java > 코딩테스트' 카테고리의 다른 글
백준 15686 (0) 2023.04.06 백준 14503 (0) 2023.04.06 [DP] 백준 풀이 기록 JAVA (Feat. do it 알고리즘 코딩테스트) (0) 2023.04.05 백준 11003(Java) (0) 2022.08.07 백준 1940, 1253, 12891(JAVA) (0) 2022.07.31