BFS : Breadth First Search
-> 근처(인접한)에 있는 것부터 찾는 알고리즘
-> Queue 이용
DFS : Depth First Search
-> 깊이 우선 순위 탐색
-> Stack 이용
문자 1, 0으로 이루어진 char[][] 배열이 주어졌고, 1은 육지, 0은 바다라 했을 때 육지의 갯수를 반환
Input : char[][] map {
{'1', '1', '0', '0', '1'},
{'1', '1', '0', '0', '0'},
{'0', '0', '0', '0', '0'},
{'0', '0', '0', '1', '1'}
}
Output : 3
1. 맞는 조건을 찾아내는 부분
int count = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (map[i][j] == '1') {
count += 1;
bfs(map, i, j);
}
}
}
2. 방향 설정 과 이차원 배열 사이즈
public static int m, n;
// 상, 하, 좌, 우
public static int[][] dirs = { { 1, 0 }, { -1, 0 }, { 0, -1 }, { 0, 1 } };
m = map.length;
n = map[0].length;
3. 큐에서 빼는 부분
Queue<int[]> q = new LinkedList<int[]>();
q.offer(new int[] { x, y });
while (!q.isEmpty()) {
int[] point = q.poll();
for (int[] dir : dirs) {
int nx = point[0] + dir[0];
int ny = point[1] + dir[1];
if (nx >= 0 && nx < m && ny >= 0 && ny < n && map[nx][ny] == '1') {
map[nx][ny] = '0';
q.offer(new int[] { nx, ny });
}
}
}
4. 조건을 확인해서 큐에 다시 넣는 부분
4.1) 상,하,좌,우로 이동했을 때 좌표의 범위
4.2) map[x][y]의 값 확인 -> 문제에서 '1'에 해당하는 부분인지
if (nx >= 0 && nx < m && ny >= 0 && ny < n && map[nx][ny] == '1') {
map[nx][ny] = '0';
q.offer(new int[] { nx, ny });
}
import java.util.*;
public class Q1 {
// 상, 하, 좌, 우
public static int[][] dirs = { { 1, 0 }, { -1, 0 }, { 0, -1 }, { 0, 1 } };
public static void main(String[] args) {
char[][] map = {
{ '1', '1', '0', '0', '1' },
{ '1', '1', '0', '0', '0' },
{ '0', '0', '0', '0', '0' },
{ '0', '0', '0', '1', '1' }
};
System.out.println(solve(map));
}
public static int solve(char[][] map) {
if (map == null || map.length == 0) {
return 0;
}
int count = 0;
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
if (map[i][j] == '1') {
count += 1;
bfs(map, i, j);
}
}
}
return count;
}
public static void bfs(char[][] map, int x, int y) {
Queue<int[]> q = new LinkedList<int[]>();
q.offer(new int[] { x, y });
while (!q.isEmpty()) {
int[] point = q.poll();
for (int[] dir : dirs) {
int nx = point[0] + dir[0];
int ny = point[1] + dir[1];
if (nx >= 0 && nx < map.length && ny >= 0 && ny < map[0].length && map[nx][ny] == '1') {
map[nx][ny] = '0';
q.offer(new int[] { nx, ny });
}
}
}
}
}
차이점 : 방향을 int[] dx, int[] dy를 만들어서 사용하고, 좌표를 저장하는 객체를 만들어서 사용함
import java.util.*;
class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
public class Q1_min {
public static int m, n;
// 상, 하, 좌, 우
public static int[] dx = { 1, -1, 0, 0 };
public static int[] dy = { 0, 0, -1, 1 };
public static void main(String[] args) {
char[][] map = { { '1', '1', '0', '0', '1' }, { '1', '1', '0', '0', '0' }, { '0', '0', '0', '0', '0' },
{ '0', '0', '0', '1', '1' } };
System.out.println(solve(map));
}
public static int solve(char[][] map) {
if (map == null || map.length == 0) {
return 0;
}
int count = 0;
m = map.length;
n = map[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (map[i][j] == '1') {
count += 1;
bfs(map, i, j);
}
}
}
return count;
}
public static void bfs(char[][] map, int x, int y) {
Queue<Point> q = new LinkedList<Point>();
q.offer(new Point(x, y));
while (!q.isEmpty()) {
Point p = q.poll();
x = p.getX();
y = p.getY();
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 0 && nx < m && ny >= 0 && ny < n && map[nx][ny] == '1') {
map[nx][ny] = '0';
q.offer(new Point(nx, ny));
}
}
}
}
}
- Basic_BFS 문제와 동일
1. 맞는 조건을 찾아내는 부분
int count = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (map[i][j] == '1') {
count += 1;
dfs(map, i, j);
}
}
}
2. 방향 설정 과 이차원 배열 사이즈
public static int m, n;
// 상, 하, 좌, 우
public static int[][] dirs = { { 1, 0 }, { -1, 0 }, { 0, -1 }, { 0, 1 } };
m = map.length;
n = map[0].length;
3. 재귀를 이용하는 부분 (stack 개념)
public static void dfs(char[][] map, int x, int y) {
if (x < 0 || y < 0 || x >= m || y >= n || map[x][y] != '1') {
return;
}
map[x][y] = '0';
for (int[] dir : dirs) {
dfs(map, x + dir[0], y + dir[1]);
}
// dfs(map, x + 1, y); // 상
// dfs(map, x - 1, y); // 하
// dfs(map, x, y - 1); // 좌
// dfs(map, x, y + 1); // 우
}
4. 조건을 확인하는 부분
4.1) 상,하,좌,우로 이동했을 때 좌표의 범위를 벗어나는지
4.2) map[x][y]의 값이 '1'이 아닌지
-> 재귀를 이용하기 때문에 위 조건이 아닐때 반환하는 형태로 구현 (중요)
if (x < 0 || y < 0 || x >= m || y >= n || map[x][y] != '1') {
return;
}
public class Q2 {
public static int m, n;
public static int[][] dirs = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };
public static void main(String[] args) {
char[][] map = {
{ '1', '1', '0', '0', '0' },
{ '1', '1', '0', '0', '0' },
{ '0', '0', '1', '0', '0' },
{ '0', '0', '0', '1', '1' } };
System.out.println(solve(map));
}
public static int solve(char[][] map) {
// error check
if (map == null || map.length == 0 || map[0].length == 0) {
return 0;
}
m = map.length;
n = map[0].length;
int count = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (map[i][j] == '1') {
count += 1;
dfs(map, i, j);
}
}
}
return count;
}
public static void dfs(char[][] map, int x, int y) {
if (x < 0 || y < 0 || x >= m || y >= n || map[x][y] != '1') {
return;
}
map[x][y] = '0';
for (int[] dir : dirs) {
dfs(map, x + dir[0], y + dir[1]);
}
// dfs(map, x + 1, y); // 상
// dfs(map, x - 1, y); // 하
// dfs(map, x, y - 1); // 좌
// dfs(map, x, y + 1); // 우
}
}
트리가 주어졌을 때 BFS를 이용하여 각 노드의 값을 출력
Input :
Output : [[1], [3,2], [4,5]]
import java.util.*;
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int val) {
this.val = val;
}
}
public class Q3 {
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
System.out.println(solve(root));
}
public static List<List<Integer>> solve(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
Queue<TreeNode> q = new LinkedList<TreeNode>();
boolean zigzag = true;
q.offer(root);
while (!q.isEmpty()) {
int size = q.size();
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < size; i++) {
TreeNode node = q.poll();
//System.out.println("node.val : " + node.val);
//System.out.println("zigzag : " + zigzag);
if (zigzag) {
list.add(node.val);
} else {
list.add(0, node.val);
}
if (node.left != null) {
q.offer(node.left);
}
if (node.right != null) {
q.offer(node.right);
}
}
zigzag = !zigzag;
result.add(list);
}
return result;
}
}
matrix가 주어졌을 때 가장 긴 증가하는 경로를 찾아 그 길이를 반환
(같은 수는 포함하면 안됨)Input : matrix =
[[9,8,3],
[6,5,7],
[2,1,1]]
Output : 4
설명)
result = [
[1,2,3],
[2,3,1],
[3,4,0]
]
따라서 1 -> 2 -> 6 -> 9 혹은 1-> 5 -> 8 -> 9 가능하고 제일 긴 길이는 4
public class Q4 {
public static int m, n;
// 상 하 좌 우
public static int[][] dirs = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
public static void main(String[] args) {
int[][] grid = { { 9, 8, 3 }, { 6, 5, 7 }, { 2, 1, 1 } };
System.out.println(solve(grid));
}
public static int solve(int[][] grid) {
if (grid.length == 0) {
return 0;
}
m = grid.length;
n = grid[0].length;
int[][] result = new int[m][n];
int max = 1;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int len = dfs(grid, i, j, result);
max = Math.max(max, len);
}
}
return max;
}
public static int dfs(int[][] grid, int i, int j, int[][] result) {
if (result[i][j] != 0) {
return result[i][j];
}
int max = 1;
for (int[] dir : dirs) {
int x = i + dir[0];
int y = j + dir[1];
if (x < 0 || x >= m || y < 0 || y >= n || grid[x][y] <= grid[i][j]) {
continue;
}
int len = 1 + dfs(grid, x, y, result);
max = Math.max(max, len);
}
result[i][j] = max;
return max;
}
}
1번 문제인 Basic_BFS에서 응용하는 문제이다.
주어진 2차원 배열에서 영역의 갯수와 그 영역의 길이 중 최대값을 출력
Input : int[][] grid = {
{ 0, 0, 3, 3 },
{ 1, 4, 0, 1 },
{ 1, 0, 0, 1 },
{ 1, 0, 0, 1 },
{ 1, 2, 2, 0 },
{ 1, 1, 0, 0 } };
Output : [5,6]
import java.util.*;
public class Q5 {
public static int m, n;
public static boolean[][] visited;
// 상 하 좌 우
public static int[][] dirs = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
public static void main(String[] args) {
int[][] grid = {
{ 0, 0, 3, 3 },
{ 1, 4, 0, 1 },
{ 1, 0, 0, 1 },
{ 1, 0, 0, 1 },
{ 1, 2, 2, 0 },
{ 1, 1, 0, 0 } };
System.out.println(Arrays.toString(solve(grid)));
}
public static int[] solve(int[][] grid) {
int maxSize = 0;
m = grid.length;
n = grid[0].length;
visited = new boolean[m][n];
int count = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (visited[i][j] || grid[i][j] == 0) {
continue;
}
count++;
int thisAreaSize = bfs(grid, i, j);
maxSize = Math.max(maxSize, thisAreaSize);
}
}
int[] result = new int[2];
result[0] = count;
result[1] = maxSize;
return result;
}
public static int bfs(int[][] grid, int i, int j) {
Queue<int[]> q = new LinkedList<int[]>();
q.offer(new int[] { i, j });
visited[i][j] = true;
int thisAreaSize = 0;
while (!q.isEmpty()) {
int[] point = q.poll();
thisAreaSize++;
for (int[] dir : dirs) {
int nx = point[0] + dir[0];
int ny = point[1] + dir[1];
if (nx >= 0 && ny >= 0 && nx < m && ny < n) {
if (!visited[nx][ny] && grid[i][j] == grid[nx][ny]) {
q.offer(new int[] { nx, ny });
visited[nx][ny] = true;
}
}
}
}
return thisAreaSize;
}
}
인프런 강의 : 코딩테스트 전 꼭 알아야 할 개념과 문제(with 자바) - 푸샵맨 코딩스터디