728x90
⬛ 05. 탐색
- 그래프의 순회 (=탐색)
- 현재 정점 처리 후 다음 처리할 정점에 대한 순서가 필요
- 한 정점에서 시작하여 그래프의 모든 정점을 한 번씩만 방문할 것.
⬛ 05-1. 깊이 우선 탐색 | DFS
- DFS는 한 번씩만 방문해야 하므로 visited[] 방문 체크 배열 필요하며 인접 리스트로 표현
🟦 백준 11724번. 연결 요소의 개수 구하기
- DFS로 깊이 방문 하다가 복귀하는 게 한 덩어리 단위임
import java.util.ArrayList;
import java.util.Scanner;
/*11724번. 연결 요소의 개수 */
public class Main {
static int N, M;
static boolean[] visited;
static ArrayList<ArrayList<Integer>> graph;
//dfs
static void dfs(int v) {
visited[v] = true;//현재 정점 방문 처리
for(int nx : graph.get(v)) { //얘의 인접 정점들에 대하여
if(!visited[nx]) {
dfs(nx);//재귀 더 깊이 방문
}
}
}
//실행 메인
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner kb= new Scanner(System.in);
N = kb.nextInt();
M = kb.nextInt();
//초기화
visited = new boolean[N+1];
//공간 생성
graph = new ArrayList<>();
for(int i=0; i<=N; i++) {
graph.add(new ArrayList<Integer>());
}
for(int i=0; i<M; i++) {
int a =kb.nextInt();
int b = kb.nextInt();
//양방향이므로 양쪽에 모두 저장
graph.get(a).add(b);
graph.get(b).add(a);
}
int answer =0;
for(int i=1; i<=N; i++) {
if(!visited[i]) {
dfs(i);//방문 안한 정점에 대하여 dfs 호출하면
answer++;//여기서 복귀하면 호출 후 복귀한 게 한 덩어리 단위임
}
}
//정답 출력
System.out.println(answer);
}
}
🟦 백준 2023번. 신기한 소수
package to_0718_1;
import java.util.Scanner;
//신기한 소수
public class Main {
static int N;//자릿수 == 깊이
static boolean visited[];//방문 체크용 배열
//소수 판별용 함수
static boolean isSosu(int a) {
for(int i=2; i<=a/2; i++) {
if(a % i == 0) {
return false;
}
}
return true;
}
//dfs
static void dfs(int num, int lv) {
if(lv == N) {//주어진 자릿수 까지 뻗은 경우
//완성된 4자리를 다시 소수 판별 후
if(isSosu(num)) {
System.out.println(num);//출력
}
return;//아니면 그냥 반환
}
for(int i=1; i<10; i++) {
if(i % 2==0) {//짝수는 그냥 건너뛰고
continue;
}
if((isSosu(num * 10 + i))) { //추가한 숫자를 현재 숫자 뒤에 이어붙여서 소수 판별
dfs(num * 10 + i, lv+1); //더 깊이 탐색
}
}
}
//실행 메인
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner kb= new Scanner(System.in);
N = kb.nextInt();
dfs(2, 1);//2로 시작하는 값 - 1의 자리
dfs(3, 1);
dfs(5, 1);
dfs(7, 1);
}
}
⬛ 05-2. 너비 우선 탐색 | BFS
- BFS는 Queue를 사용하여 가까운 인접 정점들 우선 탐색하는 특징이 존재
🟦 백준 1260번. DFS와 BFS
package to_0718_4;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/*1260번. DFS, BFS */
public class Main {
static int N, M, st;
static boolean[] visited;
static ArrayList<ArrayList<Integer>> graph;
//dfs
static void dfs(int v) {
if(!visited[v]) {
System.out.print(v + " ");//
}
visited[v] = true;
for(int nx : graph.get(v)) {
if(!visited[nx]) { //방문 안한 인접 정점에 대하여
dfs(nx);//더 깊이 탐색할 건데
}
}
}
//bfs
static void bfs(int v) {
Queue<Integer> Q = new LinkedList<>();
Q.add(v);
visited[v] = true;
while(!Q.isEmpty()) {
int cur = Q.poll();
System.out.print(cur + " "); //여기서 출력시킴
for(int nx : graph.get(cur)) {
if(!visited[nx]) {
Q.add(nx);
visited[nx] = true;//방문 처리
}
}
}
}
//실행 메인
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner kb= new Scanner(System.in);
N = kb.nextInt();
M = kb.nextInt();
st = kb.nextInt();
graph = new ArrayList<>();
for(int i=0; i<=N; i++) {
graph.add(new ArrayList<>());
}
for(int i=0; i<M; i++) {
int a =kb.nextInt();
int b = kb.nextInt();
graph.get(a).add(b);
graph.get(b).add(a);
}
//번호 작은 거 우선으로 방문하기 위해 각각 정점에 대한 정렬
for(int i=0; i<=N; i++) {
Collections.sort(graph.get(i)); //각 정점 i에 연결된 정점들 오름차순 정렬
}
visited = new boolean[N+1];
dfs(st);
System.out.println();
//visited 갱신
visited = new boolean[N+1];
bfs(st);
}
}
🟦 백준 2178번. 미로찾기
- BFS로 풀어야 하는 이유는 BFS가 인접 정점을 우선 탐색하는 애이기 때문이다.
- 자연스럽게 더 가까운 정점에 먼저 방문하므로, 방문한 정점의 값에 직전 정점 + 1 처리를 반복해서 해주면 마지막 A[][] 값은 최솟값이 담겨 있게 된다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
/*2178번. 미로 탐색 */
public class Main {
//4방향 배열
static int dx[] = {0,0, 1, -1};
static int dy[] = {1, -1, 0, 0};
static int N, M;
static boolean[][] visited; //방문 체크용 배열
static int[][] A;//원본 배열
//bfs
static void bfs(int i, int j) {
Queue<int[]> Q = new LinkedList<>();
Q.add(new int[] {i,j});
visited[i][j] = true;
while(!Q.isEmpty()) {
int[] cur = Q.poll();
//4방향으로 움직일 건데
for(int k=0; k<4; k++) {
int nx = cur[0] + dx[k];
int ny = cur[1] + dy[k];
if(nx>=0 && ny >=0 && nx<N && ny<M) {
if(A[nx][ny] !=0 && !visited[nx][ny]) {
visited[nx][ny] =true;
A[nx][ny] = A[cur[0]][cur[1]] + 1;
Q.add(new int[] {nx, ny});
}
}
}
}
}
//실행 메인
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
//데이터 입력받기
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
A = new int[N][M];
visited = new boolean[N][M];
for(int i=0; i<N; i++) {
st = new StringTokenizer(br.readLine());
String line = st.nextToken();
for(int j=0; j<M; j++) {
A[i][j] = Integer.parseInt(String.valueOf(line.charAt(j)));
}
}
bfs(0, 0);//시작 0,0에서 하고
//최종
System.out.println(A[N-1][M-1]);//0부터 시작해으니 마지막 배열에 최종 최솟값 담김
}
}
⬛ 05-3. 이진 탐색 | (=이분 검색) Binary Search
- 데이터가 정렬된 상태에서 원하는 값을 찾아내는 알고리즘
- 대상 데이터 중앙값 vs키값 비교하여 검색 범위를 절반씩 줄인다.
정렬된 자료의 중앙값 vs 키값 비교하며
- 중앙값 < 키값 : 오른쪽 부분에 대하여 탐색
- 중앙값 > 키값 : 왼쪽 부분에 대하여 탐색
- 중앙값 == 키값 : 탐색 종료
🟦 백준 1920번. 원하는 정수 찾기
import java.util.Arrays;
import java.util.Scanner;
//이분탐색
public class Main {
static int N, M;
static int A[];
//실행 메인
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner kb= new Scanner(System.in);
N = kb.nextInt();
A = new int[N];
for(int i=0; i<N; i++) {
A[i] = kb.nextInt();
}
//대상 데이터들 정렬
Arrays.sort(A);
M = kb.nextInt();
for(int i=0; i<M; i++) {
boolean find = false;
int target = kb.nextInt();
//이진 탐색 시작
int st = 0;
int ed = A.length - 1;//범위 끝에 달고
while(st <= ed) {
int mid = (st+ed) /2;
int mVal = A[mid];
if(mVal < target) {
st = mid + 1;//시작범위를 중앙+1에 두고 오르쪽 탐색
}else if(mVal > target) {
ed = mid-1;//끝범위를 중앙 -1에 두고 왼쪽 탐색
}else if(mVal == target) {
find=true;
break;
}
}
if(find) {
System.out.println(1);
}else {
System.out.println(0);
}
}
}
}
728x90
'알고리즘 이론 [개념] > [복습] 코테_알고리즘 복습' 카테고리의 다른 글
알고리즘 및 코테 복습 - DP 동적 계획법 (0) | 2023.07.25 |
---|---|
알고리즘 및 코테 복습 - 그래프(Graph) (0) | 2023.07.24 |
알고리즘 및 코테 복습 - 그리디 (Greedy) (0) | 2023.07.18 |
알고리즘 및 코테 복습 - 구간합, 투포인터, 스택과 큐 (0) | 2023.07.17 |