문제 설명
메리는 여름을 맞아 무인도로 여행을 가기 위해 지도를 보고 있습니다. 지도에는 바다와 무인도들에 대한 정보가 표시돼 있습니다. 지도는 1 x 1크기의 사각형들로 이루어진 직사각형 격자 형태이며, 격자의 각 칸에는 'X' 또는 1에서 9 사이의 자연수가 적혀있습니다. 지도의 'X'는 바다를 나타내며, 숫자는 무인도를 나타냅니다. 이때, 상, 하, 좌, 우로 연결되는 땅들은 하나의 무인도를 이룹니다. 지도의 각 칸에 적힌 숫자는 식량을 나타내는데, 상, 하, 좌, 우로 연결되는 칸에 적힌 숫자를 모두 합한 값은 해당 무인도에서 최대 며칠동안 머물 수 있는지를 나타냅니다. 어떤 섬으로 놀러 갈지 못 정한 메리는 우선 각 섬에서 최대 며칠씩 머물 수 있는지 알아본 후 놀러갈 섬을 결정하려 합니다.
지도를 나타내는 문자열 배열 maps가 매개변수로 주어질 때, 각 섬에서 최대 며칠씩 머무를 수 있는지 배열에 오름차순으로 담아 return 하는 solution 함수를 완성해주세요. 만약 지낼 수 있는 무인도가 없다면 -1을 배열에 담아 return 해주세요.
제한사항
- 3 ≤ maps의 길이 ≤ 100
- 3 ≤ maps[i]의 길이 ≤ 100
- maps[i]는 'X' 또는 1 과 9 사이의 자연수로 이루어진 문자열입니다.
- 지도는 직사각형 형태입니다.
입출력 예
maps result
["X591X","X1X5X","X231X", "1XXX1"] | [1, 1, 27] |
["XXX","XXX","XXX"] | [-1] |
입출력 예 설명
입출력 예 #1
위 문자열은 다음과 같은 지도를 나타냅니다.
연결된 땅들의 값을 합치면 다음과 같으며
이를 오름차순으로 정렬하면 [1, 1, 27]이 됩니다.
입출력 예 #2
위 문자열은 다음과 같은 지도를 나타냅니다.
섬이 존재하지 않기 때문에 -1을 배열에 담아 반환합니다.
Depth-First Search (DFS) 알고리즘을 사용해서 각각의 무인도를 탐색하고, 그 무인도에 있는 식량의 총합을 구하면 된다. DFS를 사용하여 연결된 땅들을 하나의 그룹으로 묶고, 그룹 내부의 모든 숫자를 합해주는 작업을 반복하면 된다.
package LV2;
import java.util.ArrayList;
import java.util.Collections;
public class H154540 {
private final int[] dx = {-1, 0, 1, 0}; // 상, 우, 하, 좌로 움직일 x 좌표
private final int[] dy = {0, 1, 0, -1}; // 상, 우, 하, 좌로 움직일 y 좌표
private boolean[][] visited; // 해당 좌표를 방문했는지 저장하는 배열
private String[] maps; // 주어진 지도
private int m, n; // 지도의 행과 열의 개수
private int day; // 하나의 무인도에서 머무를 수 있는 최대 일수
public int[] solution(String[] maps) {
this.maps = maps; // 지도를 클래스 변수에 저장
this.m = maps.length; // 행의 개수를 저장
this.n = maps[0].length(); // 열의 개수를 저장
this.visited = new boolean[m][n]; // 방문 배열을 생성
ArrayList<Integer> result = new ArrayList<>(); // 결과를 저장할 리스트 생성
// 지도의 모든 좌표를 순회
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
// 만약 방문하지 않았고, 무인도(숫자)라면
if(!visited[i][j] && maps[i].charAt(j) != 'X'){
this.day = 0; // 무인도에서 머무를 수 있는 일수를 0으로 초기화
dfs(i, j); // dfs를 시작
result.add(this.day); // 결과 리스트에 추가
}
}
}
// 만약 무인도가 하나도 없다면
if(result.size() == 0) {
return new int[]{-1}; // -1을 반환
} else {
int[] answer = new int[result.size()]; // 결과 배열을 생성
Collections.sort(result); // 결과 리스트를 정렬
// 결과 배열에 리스트의 원소를 차례대로 넣음
for(int i=0; i<result.size(); i++) answer[i] = result.get(i);
return answer; // 결과 배열을 반환
}
}
// DFS 메소드
public void dfs(int x, int y) {
visited[x][y] = true; // 해당 좌표를 방문했음을 표시
day += maps[x].charAt(y) - '0'; // 무인도에서 머무를 수 있는 일수에 해당 좌표의 값을 더함
// 상, 우, 하, 좌 순서로 방문 가능한지 확인
for(int i=0; i<4; i++){
int nx = x + dx[i]; // 다음 x 좌표
int ny = y + dy[i]; // 다음 y 좌표
// 만약 다음 좌표가 지도 내부에 있고,
if(nx >= 0 && nx < m && ny >= 0 && ny < n){
// 다음 좌표를 아직 방문하지 않았으며, 무인도(숫자)라면
if(!visited[nx][ny] && maps[nx].charAt(ny) != 'X'){
dfs(nx, ny); // dfs를 계속 진행
}
}
}
}
}
'maps' 문자열 배열을 받아 각 요소를 순회하며 무인도를 찾아내고, 각 무인도의 총 식량 양을 구하여 오름차순으로 정렬한 뒤 결과를 반환한다. 만약 무인도가 없다면 -1을 반환한다.
이 코드에서 DFS 함수는 각 좌표를 방문하고 4방향을 확인해서 이동 가능한 즉, 무인도인 좌표가 있는지 확인하고 있다. 이동 가능한 좌표가 있다면 해당 좌표를 다시 DFS 함수에 넣어 재귀적으로 방문하는 방식이다. 이 과정을 통해 연결된 무인도를 모두 탐색하고 그 식량 양을 합산할 수 있다.
'알고리즘 > 프로그래머스 JAVA LV.2' 카테고리의 다른 글
전력망을 둘로 나누기 (0) | 2023.06.20 |
---|---|
숫자 카드 나누기 (0) | 2023.06.20 |
테이블 해시 함수 (0) | 2023.06.19 |
줄 서는 방법 (0) | 2023.06.16 |
가장 큰 정사각형 찾기 (0) | 2023.06.15 |