오늘보다 더 나은 내일의 나에게_

자바 알고리즘 문제 풀이 Array Q10_봉우리 본문

ALGORITHM/inflearn_javaAlgorithm

자바 알고리즘 문제 풀이 Array Q10_봉우리

chan_96 2022. 2. 19. 15:22
728x90
설명

지도 정보가 N*N 격자판에 주어집니다. 각 격자에는 그 지역의 높이가 쓰여있습니다.

각 격자판의 숫자 중 자신의 상하좌우 숫자보다 큰 숫자는 봉우리 지역입니다. 봉우리 지역이 몇 개 있는 지 알아내는 프로그램을 작성하세요.

격자의 가장자리는 0으로 초기화되었다고 가정한다.

만약 N=5이고, 격자판의 숫자가 다음과 같다면 봉우리의 개수는 10개입니다.


입력

첫 줄에 자연수 N이 주어진다.(2 <=N <=50)

두 번째 줄부터 N 줄에 걸쳐 각 줄에 N개의 자연수가 주어진다. 각 자연수는 100을 넘지 않는다.


출력

봉우리의 개수를 출력하세요.

 


예시 입력1


예시 출력

5
5 3 7 2 3
3 7 1 6 1
7 2 5 3 4
4 3 6 4 1
8 7 3 5 2
10

 

코드

내가 입력한 코드

더보기
package Array;

import java.util.Scanner;

public class Q10 {
	public int solution(int n, int[][] arr) {
		int answer = 0;
		int[][] arr2 = new int[n+2][n+2];
	
		//배열 0으로 채우기
		for (int i = 0; i < n+2; i++) {
			arr2[0][i] = 0;
			arr2[n+1][i] = 0;
			
			for (int j = 1; j < n+1; j++) {
				arr[j][0] = 0;
				arr[j][n+1] = 0;
			}
		}
		
		//main에서 입력받은 arr배열을 arr2배열에 채우기
		for (int i = 1; i < n+1; i++) {
			for (int j = 1; j < n+1; j++) {
				arr2[i][j] = arr[i-1][j-1];
			}
		}
		
		//봉우리갯수 구하기
		for (int i = 1; i < n+1; i++) {
			for (int j = 1; j < n+1; j++) {
				if(arr2[i][j] > arr2[i][j-1] && arr2[i][j] > arr2[i][j+1] && arr2[i][j] > arr2[i-1][j] && arr2[i][j] > arr2[i+1][j]) answer++;
			}
		}
		
		return answer;
	}
	
	public static void main(String[] args) {
		Q10 T = new Q10();
		Scanner kb = new Scanner(System.in);
		int n = kb.nextInt();
		int[][] arr = new int[n][n];
		
		System.out.println(T.solution(n, arr));
	}
}

 



해설 코드

import java.util.*;
class Main {	
	int[] dx={-1, 0, 1, 0};
	int[] dy={0, 1, 0, -1};
	public int solution(int n, int[][] arr){
		int answer=0;
		for(int i=0; i<n; i++){
			for(int j=0; j<n; j++){
				boolean flag=true;
				for(int k=0; k<4; k++){
					int nx=i+dx[k];
					int ny=j+dy[k];
					if(nx>=0 && nx<n && ny>=0 && ny<n && arr[nx][ny]>=arr[i][j]){
						flag=false;
						break;
					}
				}
				if(flag) answer++;
			}
		}
		return answer;
	}

	public static void main(String[] args){
		Main T = new Main();
		Scanner kb = new Scanner(System.in);
		int n=kb.nextInt();
		int[][] arr=new int[n][n];
		for(int i=0; i<n; i++){
			for(int j=0; j<n; j++){
				arr[i][j]=kb.nextInt();
			}
		}
		System.out.print(T.solution(n, arr));
	}
}

 

 

풀이 및 정리 

역시 이번에도 채점 결과 런타임 에러... 문제 푸는 방식이 틀렸나 보다😭

해설 코드에서는 3중 for문을 사용하였다. 나는 입력받은 2차원 배열 주위에 0을 따로 채웠는데 그럴 필요가 없었다. 문제에서 구하는 값이 어떤 값을 중심으로 상하좌우 값들보다 큰 개수를 구하는 문제이다. 그렇다면 값 하나를 정해놓고 상하좌우 비교하는 알고리즘을 구해보면 문제를 풀 수 있다.

2중 for문이 작성됐다고 가정하고 2차원 배열의 변수를 arr이라고 하자.
i는 행, j는 열
arr [0][0]의 값은 5이고
상:0 => arr[i-1][j]
하:3 => arr[i+1][j]
좌:0 => arr[i][j-1]
우:3
=> arr[i][j+1]
이런 식으로 반복이 될 수 있다. 그렇지만 arr[0][0]의 상:0 좌:0 값은 실제로 존재하지 않고 이를 무시한 체 코드를 작성하면 ArrayIndexOutOfBoundsException 예외가 발생해 이 또한 고려해서 코드를 작성해야 한다.

위와 같이 값하나 하나 비교를 할 때 arr[i-1][j], arr[i+1][j], arr[i][j+1], arr[i][j-1] 이런 식으로 조건문에서 비교를 한다면 가독성도 떨어지고 비효율적이다.
행과 열에 따른 들어갈 숫자를 배열로 만들어 주면 된다. 시계방향으로 값을 비교한다고 했을 때
상우하좌 비교할 값의 행의 인덱스를 보면 i-1, i, i+1, i인데 이걸 -1, 0, 1, 0 값이 반복된다고 볼 수 있고
열 또한 j, j-1, j, j+1인데 이걸 0, 1, 0,-1 값이 반복된다고 볼 수 있어 배열로 만들어 사용하면 훨씬 간편해진다.

 

int[] dx={-1, 0, 1, 0};
int[] dy={0, 1, 0, -1};​

 

arr[i][j]에서 i에 행의 값인 dx배열의 0번째 -1와 i를 더해주고 j에는 열의 값인 dy배열의 0번째 인덱스 0을 j와 더해준다. 정리하면 arr[i+dx[k]][j+dy[k]]가 반복된다고 할 수 있다. (k의 값은 3중 for문의 변수 k)
arr[i+dx[k]][j+dy[k]]값을 이제 배열의 각 인덱스 값과 비교해주면 된다.

여기서 주의할 점이 존재하지 않은 인덱스와 비교하게 될 수 있어서 i+dx[k], j+dy[k]값은 반드시 0보다 커야 하고 처음에 입력한 정수 n보다는 작아야 한다. 그래야 ArrayIndexOutOfBoundsException가 발생하지 않는다.

 

728x90
Comments