<문제 제시>
<문제설명>
다음 그림과 같이 지뢰가 있는 지역과 지뢰에 인접한 위, 아래, 좌, 우 대각선 칸을
모두 위험지역으로 분류합니다.
지뢰는 2차원 배열 board에 1로 표시되어 있고 board에는
지뢰가 매설 된 지역 1과, 지뢰가 없는 지역 0만 존재합니다.
지뢰가 매설된 지역의 지도 board가 매개변수로 주어질 때,
안전한 지역의 칸 수를 return하도록 solution 함수를 완성해주세요.
배열은 n * n 배열
<예시 입출력>
<문제 해결 과정>
안전지대 문제는 다른 기업들의 코테문제와 유사한 느낌의 2차원 배열을 다루는 문제로
필수적으로 알아야할 부분들이 많을 것 같았다.
int answer = 0;
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[i].length; j++) {
if(board[i][j] == 1) {
System.out.println("###");
System.out.println("지뢰 발견 ! 좌표 = (" + board[i] + ", " + board[j] + ")");
}
}
}
return answer;
보드에서의 지뢰가 발견되었을때 프린트문을 간단히 작성해보았으나 막막하였다.
2차원 배열의 출력구조에 더 익숙해져야겠다고 생각했다.더 공부해야겠다는 생각이 들었다.
Solution 1)
1. 복제 좌표 변수를 만든다.
2. 내용물을 복제한다.
>> for(int [] rows : board)
동시에 2차원배열을 처리할 필요 없이 rows(행)으로 받아 c_board의 행에 입력하고,
그 다음 데이터로 넘어가는 방식을 취함
이때 Arrays.copyOf 함수를 사용하는데, 이는 (원본배열, 원본배열에서 복사하고싶은 요소들의 길이) 를 입력받는다.
>> Arrays.copyOf와 System.arraycopy() 함수로 배열을 복사할 수 있는데, 두 메서드의 차이점이 있다.
1) Arrays.copyOf : 새로운 배열 생성 가능, 전부 복사하거나 복사 대상의 객체를 유지시킬 필요가 없을 때 사용 추천.
2) System.arraycopy() : 복사 길이를 명시해야 하거나, 객체를 유지하고자 할 때 사용 추천.
>> Arrays.copyOf가 처리속도에서 2배가량 빠르다는 말도 있다.
3. (조건문 일치)
중첩 반복문을 통해 특정 값을 변수에 담고 그 값이 0이면 지속해서 반복하는방식으로 설계
그렇지 않으면, 지뢰 처리 함수로 이동하는데, 인자로 x,y인덱스와 폭발범위, 복제된 배열을 전달한다.
for(int r = row - range; r<= row + range ; r++){
if(r < 0 || r >= board.length) continue;
for(int c = col - range; c <= col + range; c++){
if(c < 0 || c >= board[0].length) continue;
}
}
이 알고리즘의 핵심로직은 이러하다.
//★
if(r < 0 || r >= board.length) continue;
특히 이 부분에서
>> ex) 테스트케이스 1번의 경우 [3][2] 에서 검출이 되므로
1) row = 검출된 행인 인덱스는 (3) 이다.
2) range는 1로 주어지고 있으므로 r = 3 - 1 = 2 이다.
3) r이 3 + 1 = 4가 될때까지 반복한다.
4) for(int r = 2; r <= 4; r++)
>> r = 2, r = 3, r = 4
>> 이 경우 실제 지뢰가 검출된 r = 3행을 포함한 위 아래 r = 2, r = 4또한 검사한다.
5) for(int c = 1; c <= 3; c++)
>> c = 1, c = 2, c = 3
>> 이 경우에도 실제 지뢰가 검출된 c = 2행을 포함한 양 옆 c = 1, c = 3또한 검사한다.
6) if문은 예외처리 구문, 값이 0보다 작아지거나 board의 행 길이보다 같거나 길어진다면 continue
7) 이 예외처리들이 해당하지 않으면 board[r][c] = 1로 [r][c]에 해당하는 값을 1로 초기화시킨다.
8) 다시 메인처리에서 중첩 반복문을 돌려 값이 0이게되면 answer에 누적하여 안전한 지대의 칸수를 카운트한다.
<전체코드>
import java.util.Arrays;
public class safe_zone {
public static int solution(int[][] board) {
int answer = 0;
int range = 1;
int[][] c_board = new int[board.length][board[0].length];
int k = 0;
for (int[] rows : board) {
c_board[k] = Arrays.copyOf(rows, board[k].length);
k++;
}
System.out.println(Arrays.deepToString(c_board));
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
int val = board[i][j];
if(val == 0) continue;
System.out.print("검출된 지뢰 좌표 = [" + i + ", " + j+ "]\n");
System.out.println("그 해당 값 = " + val);
makeBoomArea(i, j, range,c_board);
}
}
System.out.println("지뢰의 범위 처리 후 board = " + Arrays.deepToString(board));
System.out.println("지뢰의 범위 처리 후 c_board = " + Arrays.deepToString(c_board));
for (int[] ints : c_board) {
for (int anInt : ints) {
if(anInt == 0)
answer++;
}
}
return answer;
}
// 인자로는 복제된 c_board가 전달되었지만 함수 처리시에는 board로 처리한다.
// 결국 값 변동은 c_board에 있다.
private static void makeBoomArea(int row, int col, int range, int[][] board) {
for (int r = row - range; r <= row + range ; r++) {
if(r < 0 || r >= board.length) {
System.out.println("지뢰의 행 범위가 " + r + "이므로 다음으로 넘어갑니다.");
continue;
}
System.out.print("지뢰의 행 범위 = " + r + " >> ");
for (int c = col - range; c <= col + range; c++) {
if(c < 0 || c >= board[0].length) {
System.out.println("지뢰의 열 범위가 " + c + "이므로 다음으로 넘어갑니다.");
continue;
}
System.out.print(c + ", ");
board[r][c] = 1;
}
System.out.println();
}
}
public static void main(String[] args) {
// {0, 0, 0, 0, 0} 이므로 5x5행렬
int[][] board = {{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 1, 0, 0},
{0, 0, 0, 0, 0}};
System.out.println(solution(board));
}
}
2차원배열을 활용하는 문제는 항상 어렵다고 느낀다. 특히나 이미지를 연상해가며 좌표에서 특정한 조건을 만족하는
대상을 찾는 것이 어려웠다.
문제링크)
https://school.programmers.co.kr/learn/courses/30/lessons/120866
'Algorithms > 프로그래머스' 카테고리의 다른 글
[프로그래머스] '외계어 사전' - Java (0) | 2023.05.18 |
---|---|
[프로그래머스] '삼각형의 완성조건 (2)' - Java (1) | 2023.05.17 |
[프로그래머스] '숨어있는 숫자의 덧셈 (2)' - Java (0) | 2023.05.16 |
[프로그래머스] '다항식 더하기' - Java (0) | 2023.05.15 |
[프로그래머스] '최댓값 만들기 (2)' - Java (0) | 2023.05.15 |