문제
: N by N의 격자판(2차원 배열) 이 주어진다. 이 격자판을 구성하는 각 element 값은 - 그 "지역"의 "높이" 로 간주한다. 그리고 이 격자판을 구성하는 N*N개의 지역 중, "각 지역을 기준으로 자신의 상-하-좌-우 보다 더 높이가 높은 지역"을 "봉우리"로 칭한다. (단 상-하-좌-우 지역의 높이를 비교할 때 , 가장자리를 벗어나면 높이를 0으로 간주한다.)
이때 N by N의 격자판이 입력으로 주어지면 , 이중 봉우리의 개수를 구하라.
(2<=N<=50 , 각 지역의 높이는 자연수 100을 넘지 않는다.)
이 문제의 요구사항은 주어진 대로 2차원 배열의 각 element 값을 비교하여 봉우리의 조건을 만족하는 element의 개수를 count 하는 것이다.
나는 이에 따른 해결로직으로 (row,col)의 값을 넘기면 , 그 위치의 element값을 (row,col-1) / (row, col+1) / (row-1, col) / (row+1, col)의 좌-우-상-하 값하고 비교하여 봉우리를 판단하는 방식을 생각했다.
그런데 이를 구현하는 방식에 었어 나와 선생님의 방식은 조금 차이가 있었다.
[구현 방식의 차이]
1. 나의 경우
- 단순히 (row,col)의 값과 , (row,col-1) / (row, col+1) / (row-1, col) / (row+1, col)의 값을 4번 비교하여 , 그 결과를 && 연산자로 묶었다.
- 이렇게 하면 요구하는 대로 각 지역 기준 , 좌-우-상-하 보다 모두 높이가 큰 지역을 찾을 수 있다.
- 그러나 if문 안의 조건문이 or 중첩 if문을 사용한다면 if문의 크기가 커질 수 밖에 없고 -> 이는 가독성 저하로 나타난다.
- 선생님 방식
- 반면 선생님 께서는 int[] row = {0 , 0, -1, 1} / int[] col = {-1, 1, 0, 0} 의 방향 배열을 사용하셨다.
- 이 방향 배열을 for문과 함께 사용하면 , 4번의 비교를 같은 코드로 할 수 있고
-> 이는 결과적으로 코드의 가독성을 높였다.
(만약 비교해야할 횟수가 8개 12개라면 ? )- 따라서 이 방향 배열을 사용하는 방식으로 문제를 다시한번 풀어보았고 , 이 방식에 더 익숙해져야 겠다고 느꼈다.
[주목할 점]
: 사실 위의 차이보다 본질적으로 중요한 내용은, 가장자리를 벗어난 부분의 높이를 0으로 처리한다고 주어졌는데 -> 이를 코드로 어떻게 구현할 것인가 라고 생각한다.
- 나의 경우는 문제의 예시 그림으로 가장자리가 모두 0으로 채워진 그림을 보고, 나 또한 입력받은 값을 기반으로 가장자리를 모두 0으로 채웠지만
- 저 그림이 없없다면 가장자리를 0으로 채울 생각이 바로 들었을지 잘 모르겠다.
- 이처럼 특정 문제의 조건이 주어졌을 때 -> 이를 어떤식으로 활용해야 할지를 떠올리는 능력을 키워야 겠다고 느꼈다.
아래는 내가 거대한 조건문을 쓴 if문으로 봉우리를 판단한 코드와,
선생님의 방식으로 방향 배열을 사용하여 봉우리를 판단한 코드를 첨부하겠다.
1) 나의 코드
import java.util.Scanner;
public class Main {
public static int solution(int[][] arr, int N){
int cntOfPeak = 0;
for(int i=1; i<=N; i++){
for(int j=1; j<=N; j++){
if(isPeak(arr, i, j))
cntOfPeak++;
}
}
return cntOfPeak;
}
public static boolean isPeak(int[][] arr, int centerRow, int centerCol){
int centerValue = arr[centerRow][centerCol];
if(centerValue > arr[centerRow-1][centerCol] && centerValue > arr[centerRow+1][centerCol]
&& centerValue > arr[centerRow][centerCol-1] && centerValue > arr[centerRow][centerCol+1])
return true;
else
return false;
}
public static void main(String[] args) {
//0.Scanner 준비
Scanner sc = new Scanner(System.in);
//1. 입력
int N = sc.nextInt();
//배열을 생성만 하고 초기화 하지 않으면 -> primitive 타입은 0으로 , 객체 타입은 null로 자동 초기화 됨
int[][] arr = new int[N+2][N+2];
for(int i=1; i<=N; i++){
for(int j=1; j<=N; j++){
arr[i][j] = sc.nextInt();
}
}
//2. solution() 호출하여 결과 반환
int numOfPeaks = solution(arr, N);
//3. 결과 출력
System.out.println(numOfPeaks);
}
}
2) 선생님 방식을 적용한 코드
import java.util.Scanner;
public class Main2 {
static int[] row = {0, 0, -1, 1};
static int[] col = {-1, 1, 0, 0};
public static int solution(int[][] arr , int N){
int numOfPeak = 0;
for(int i=1; i<=N; i++){
for(int j=1; j<=N; j++){
if(isPeak(arr, i, j)) numOfPeak++;
}
}
return numOfPeak;
}
public static boolean isPeak(int[][] arr, int centerRow, int centerCol){
for(int i=0; i<4; i++){
if(arr[centerRow][centerCol] <= arr[centerRow + row[i]][centerCol + col[i]])
return false;
}
return true;
}
public static void main(String[] args) {
//0.Scanner 준비
Scanner sc = new Scanner(System.in);
//1. 입력
int N = sc.nextInt();
//배열을 생성만 하고 초기화 하지 않으면 -> primitive 타입은 0으로 , 객체 타입은 null로 자동 초기화 됨
int[][] arr = new int[N+2][N+2];
for(int i=1; i<=N; i++){
for(int j=1; j<=N; j++){
arr[i][j] = sc.nextInt();
}
}
//2. solution() 호출하여 결과 반환
int numOfPeaks = solution(arr, N);
//3. 결과 출력
System.out.println(numOfPeaks);
}
}