2024. 3. 16. 16:22ㆍ코딩 테스트/[프로그래머스] Java
문제 설명
문제 풀이
[try1]
class Solution {
public int solution(int[][] board) {
int answer = 0;
for(int i=0; i<board.length; i++){
for(int j=0; j<board[i].length; j++){
System.out.println("("+i+","+j+") "+board[i][j]);
}
}
return answer;
}
}
우선 각 원소의 위치를 i,j로 얻고 그 값을 출력해보았다.
이제 이 값이 1일 경우, 그 주변인 상하좌우를 위험지역으로 분류해야한다.
여기서 주의해야 할 부분이 무엇이 있을 지 생각해 보았다!
1. 가장자리의 경우, 더 이상 위험 지역으로 분류될 공간이 없다.
예시) i==0 또는 i==board.length-1 또는 j==0 또는 j==board[i].length 같은 좌표인 값을 주의하자.
2. 지뢰가 한 칸 옆일 경우, 지뢰인 부분은 위험 지역으로 분류되지 않는다.
지뢰의 좌표가 -1,+1씩 차이가 나는 경우, 해당 좌표로의 위험 지역 분류는 하지 않도록 주의하자.
3. 지뢰가 두 칸 옆일 경우, 두 개의 지뢰에게 적용되는 위험 지역의 개수에서 중복되는 공간의 개수를 제거한다.
지뢰의 좌표가 -2,+2씩 차이가 나는 경우, 해당 좌표로의 위험 지역 분류 후 중복되는 좌표는 제거하자.
위 경우의 수를 생각해 보았다면, 이제는 어떻게 지뢰와 위험 지역의 좌표를 저장할 것인지에 대해서 고민해야 한다.
위험 지역 좌표를 저장할 배열을 새로 생성하여 저장하는 방법으로 나머지 코드를 작성해보았다.
class Solution {
public int solution(int[][] board) {
int[][] danger = new int[board.length][board[0].length];
int bomb = 0;
int answer = 0;
for(int i=0; i<board.length; i++){
for(int j=0; j<board[i].length; j++){
//System.out.println("("+i+","+j+") "+board[i][j]);
if(board[i][j]==1 & i!=0 & j!=0 & i!=board.length-1 & j!=board[i].length-1){
bomb+=1;
danger[i][j+1] = 2;
danger[i][j-1] = 2;
danger[i+1][j] = 2;
danger[i-1][j] = 2;
danger[i+1][j+1] = 2;
danger[i-1][j+1] = 2;
danger[i+1][j-1] = 2;
danger[i-1][j-1] = 2;
}else if(board[i][j]==1 & i==0 & j!=0 & i!=board.length-1 & j!=board[i].length-1){
bomb+=1;
danger[i][j+1] = 2;
danger[i][j-1] = 2;
danger[i+1][j] = 2;
danger[i+1][j+1] = 2;
danger[i+1][j-1] = 2;
}else if(board[i][j]==1 & i!=0 & j==0 & i!=board.length-1 & j!=board[i].length-1){
bomb+=1;
danger[i][j+1] = 2;
danger[i+1][j] = 2;
danger[i-1][j] = 2;
danger[i+1][j+1] = 2;
danger[i-1][j+1] = 2;
}else if(board[i][j]==1 & i!=0 & j!=0 & i==board.length-1 & j!=board[i].length-1){
bomb+=1;
danger[i][j+1] = 2;
danger[i][j-1] = 2;
danger[i-1][j] = 2;
danger[i-1][j+1] = 2;
danger[i-1][j-1] = 2;
}else if(board[i][j]==1 & i!=0 & j!=0 & i!=board.length-1 & j==board[i].length-1){
bomb+=1;
danger[i][j-1] = 2;
danger[i+1][j] = 2;
danger[i-1][j] = 2;
danger[i+1][j-1] = 2;
danger[i-1][j-1] = 2;
}
}
}
for(int i=0; i<board.length; i++){
for(int j=0; j<board[i].length; j++){
System.out.println("("+i+","+j+") "+danger[i][j]);
if(danger[i][j]==2) answer+=1;
}
}
return board.length*board[0].length - bomb - answer;
}
}
위 코드는 가장자리인 경우에 대해서만 작성한 것이다..
이것만으로도 코드가 너무 길어진다!
하지만 다른 경우도 추가해서 우선 작성해 보자.
[try2]
class Solution {
public int solution(int[][] board) {
int[][] danger = new int[board.length][board[0].length];
int bomb = 0;
int answer = 0;
for(int i=0; i<board.length; i++){
for(int j=0; j<board[i].length; j++){
//System.out.println("("+i+","+j+") "+board[i][j]);
if(board[i][j]==1 && i!=0 && j!=0 && i!=board.length-1 && j!=board[i].length-1){
if(board[i+1][j]==1 || board[i-1][j]==1 || board[i][j-1]==1 || board[i][j+1]==1) answer-=1;
bomb+=1;
danger[i][j+1] = 2;
danger[i][j-1] = 2;
danger[i+1][j] = 2;
danger[i-1][j] = 2;
danger[i+1][j+1] = 2;
danger[i-1][j+1] = 2;
danger[i+1][j-1] = 2;
danger[i-1][j-1] = 2;
}else if(board[i][j]==1 && i==0 && j!=0 && i!=board.length-1 && j!=board[i].length-1){
if(board[i+1][j]==1 || board[i][j-1]==1 || board[i][j+1]==1) answer-=1;
bomb+=1;
danger[i][j+1] = 2;
danger[i][j-1] = 2;
danger[i+1][j] = 2;
danger[i+1][j+1] = 2;
danger[i+1][j-1] = 2;
}else if(board[i][j]==1 && i!=0 && j==0 && i!=board.length-1 && j!=board[i].length-1){
if(board[i+1][j]==1 || board[i-1][j]==1 || board[i][j+1]==1) answer-=1;
bomb+=1;
danger[i][j+1] = 2;
danger[i+1][j] = 2;
danger[i-1][j] = 2;
danger[i+1][j+1] = 2;
danger[i-1][j+1] = 2;
}else if(board[i][j]==1 && i!=0 && j!=0 && i==board.length-1 && j!=board[i].length-1){
if(board[i-1][j]==1 || board[i][j-1]==1 || board[i][j+1]==1) answer-=1;
bomb+=1;
danger[i][j+1] = 2;
danger[i][j-1] = 2;
danger[i-1][j] = 2;
danger[i-1][j+1] = 2;
danger[i-1][j-1] = 2;
}else if(board[i][j]==1 && i!=0 && j!=0 && i!=board.length-1 && j==board[i].length-1){
if(board[i+1][j]==1 || board[i-1][j]==1 || board[i][j-1]==1) answer-=1;
bomb+=1;
danger[i][j-1] = 2;
danger[i+1][j] = 2;
danger[i-1][j] = 2;
danger[i+1][j-1] = 2;
danger[i-1][j-1] = 2;
}
}
}
for(int i=0; i<board.length; i++){
for(int j=0; j<board[i].length; j++){
System.out.println("("+i+","+j+") "+danger[i][j]);
if(danger[i][j]==2) answer+=1;
}
}
System.out.println(bomb);
return board.length*board[0].length - bomb - answer;
}
}
[try3]
사실 어느 부분에서 어떻게 잘못되어가고 있는지 눈으로 잘 확인할 수가 없다..
그래서 중복되는 부분이나 복잡한 부분을 조금 다듬고 진행하기로 했다.
class Solution {
public int solution(int[][] board) {
int[][] danger = new int[board.length][board[0].length];
int bomb = 0; //폭탄의 개수
int dan = 0; //위험 지역의 개수
int answer = 0; //안전 지역의 개수
int row_end = board.length-1;
int col_end = board[0].length-1;
int total = (row_end+1) * (col_end+1);
for(int i=0; i<board.length; i++){
for(int j=0; j<board[i].length; j++){
/*폭탄이 1개 또는 2칸 이상 떨어져 있는 경우*/
if(board[i][j]==1){
danger[i][j]=2;
/*폭탄이 인접한 경우
if (i > 0 && board[i - 1][j] == 1) dan -= 1;
if (j > 0 && board[i][j - 1] == 1) dan -= 1;*/
/*폭탄이 가장자리인 경우*/
if(i==0){ //위쪽 가장자리
if(0<j && j<col_end){ //좌우 가장자리 제외
danger[i+1][j] = 2; //하
danger[i+1][j+1] = 2; //하우
danger[i+1][j-1] = 2; //하좌
danger[i][j-1] = 2; //좌
danger[i][j+1] = 2; //우
}else if(j==0){
danger[i][j+1] = 2; //우
danger[i+1][j] = 2; //하
danger[i+1][j+1] = 2; //하우
}else if(j==col_end){
danger[i][j-1] = 2; //좌
danger[i+1][j] = 2; //하
danger[i+1][j-1] = 2; //하좌
}
}else if(i==row_end){ //아래쪽 가장자리
if(0<j && j<col_end){ //좌우 가장자리 제외
danger[i-1][j] = 2; //상
danger[i-1][j+1] = 2; //상우
danger[i-1][j-1] = 2; //상좌
danger[i][j-1] = 2; //좌
danger[i][j+1] = 2; //우
}else if(j==0){
danger[i][j+1] = 2; //우
danger[i-1][j] = 2; //상
danger[i-1][j+1] = 2; //상우
}else if(j==col_end){
danger[i][j-1] = 2; //좌
danger[i-1][j] = 2; //상
danger[i-1][j-1] = 2; //상좌
}
}/*폭탄이 내부인 경우*/
else{
if(j==0){
danger[i-1][j] = 2; //상
danger[i+1][j] = 2; //하
danger[i-1][j+1] = 2; //상우
danger[i+1][j+1] = 2; //하우
danger[i][j+1] = 2; //우
}else if(j==col_end){
danger[i-1][j] = 2; //상
danger[i+1][j] = 2; //하
danger[i-1][j-1] = 2; //상좌
danger[i+1][j-1] = 2; //하좌
danger[i][j-1] = 2; //좌
}else{
danger[i-1][j] = 2; //상
danger[i+1][j] = 2; //하
danger[i-1][j+1] = 2; //상우
danger[i-1][j-1] = 2; //상좌
danger[i][j-1] = 2; //좌
danger[i][j+1] = 2; //우
danger[i+1][j+1] = 2; //하우
danger[i+1][j-1] = 2; //하좌
}
}
}
}
}
for(int i=0; i<board.length; i++){
for(int j=0; j<board[i].length; j++){
System.out.println("("+i+","+j+") "+danger[i][j]);
if(danger[i][j]==2) dan+=1;
}
}
return total-dan;
}
}
잘 되는 줄 알았는데... 테스트 9에서 런타임에러가 발생했다!
너무 복잡하게 작성한 탓인 것 같았다 😂
반복되는 상하좌우 방향을 설정하는 부분도 없애야 했다!!
[try3]
class Solution {
public int solution(int[][] board) {
int row = board.length;
int col = board[0].length;
int[][] danger = new int[board.length][board[0].length];
int dan = 0; //위험 지역의 개수
for(int i=0; i<row; i++){
for(int j=0; j<col; j++){
if(board[i][j]==1){
danger[i][j]=1;
if(i > 0) danger[i-1][j] =1; //상
if(i < row-1) danger[i+1][j] =1; //하
if(j < col-1) danger[i][j+1] =1; //우
if(j > 0) danger[i][j-1] =1; //좌
if(i > 0 && j>0) danger[i-1][j-1] =1; //상좌
if(i < row-1 && j>0) danger[i+1][j-1] =1; //하좌
if(i > 0 && j<col-1) danger[i-1][j+1] =1; //하우
if(i < row-1 && j<col-1) danger[i+1][j+1] =1; //상우
}
}
}
for(int i=0; i<row; i++){
for(int j=0; j<col; j++){
if(danger[i][j]==1) dan+=1;
}
}
return col*row-dan;
}
}
이전에는 경우의 수를 한줄 한줄 나누어주었다면,
이번에는 범위를 나누어서 전체적으로 적용해주는 방법을 선택했다.
훨씬 간단하게 적을 수 있었는데, 왜 매번 하나부터 열까지 다 경우의 수를 적용하려고 하는지
이 안좋은 습관이 하루빨리 고쳐지면 좋겠다....😶🌫️
다른 사람의 풀이 보기
1. 가장자리의 경우의 수를 구하기 번거롭기 때문에 처음부터 위험 지역을 저장할 배열의 크기를 +2씩 늘려서 생성한다. 이렇게 되면 가장자리에서 indexoutofrange error가 발생할 위험을 줄인다.
'코딩 테스트 > [프로그래머스] Java' 카테고리의 다른 글
[코딩테스트연습] 코딩테스트 입문 > Lv.0 옷가게 할인받기 (0) | 2024.03.18 |
---|---|
[코딩테스트연습] 코딩테스트 입문 > Lv.0 삼각형의 완성조건(1) (0) | 2024.03.18 |
[코딩테스트연습] 코딩테스트 입문 > Lv.0 평행 (0) | 2024.03.16 |
[코딩테스트연습] 코딩테스트 입문 > Lv.0 문자열안에 문자열 (0) | 2024.03.16 |
[코딩테스트연습] 코딩테스트 입문 > Lv.0 최댓값 만들기(1) (0) | 2024.03.16 |