코딩테스트 - 프로그래머스/JAVA

[프로그래머스 / 깊이/너비 우선 탐색(DFS/BFS) / 자바(JAVA)] 게임 맵 최단거리

읁; 2024. 5. 19. 21:47

[프로그래머스 / 깊이/너비 우선 탐색(DFS/BFS) / 자바(JAVA)] 게임 맵 최단거리

문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/1844

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

[ 요약 ]

더보기
더보기

시작 시간 : PM 7:07

종료 시간 : PM 8:45

소요 시간(분) : 98분

 

도전 횟수 (제출 횟수) : 4

로직 및 풀이 참고 여부 : O
https://velog.io/@minji0801/오답노트파이썬-프로그래머스-게임-맵-최단거리

 

[ 풀어보기 ]

 

정답 풀이

📌 로직

  1. BFS(너비 우선 탐색). Queue를 이용해서 구현할 수 있다.
    • 시작 노드를 Queue에 넣는다.
    • Queue에서 노드를 꺼내고, 인접 노드 중 방문하지 않은 노드를 Queue에 넣는다.
    • 2번 과정을 Queue에 노드가 없을 때까지 반복한다.

 

📌 코드

import java.util.*;

class Solution {

    int[][] maps;
    int n = 0;
    int m = 0;
    
    public int solution(int[][] maps) {
        
        n = maps.length;
        m = maps[0].length;
        this.maps = maps;

        int answer = bfs(0,0);
        return (answer == 1) ? -1 : answer;
        // answer이 1이면 방문할 수 없다는 뜻 => -1을 return 한다.
    }
    
    private int bfs(int x, int y) {
        
        // 상, 하, 좌, 우를 살펴주기 위한 배열
        int[] dx = {-1, 1, 0, 0}; // 행 이동
        int[] dy = {0, 0, -1, 1}; // 열 이동

        Queue q = new LinkedList();
        // Queue에는 현재 방문한 좌표로부터
        // 인접한 노드들 중, 방문하지 않은 노드를 넣어줄 것.
        
        int[] a = {x, y}; // 시작점
        q.add(a); // Queue에 넣어준다.
        
        while(!q.isEmpty()) {
            
            int[] b = (int[])q.poll(); // 노드를 꺼내준다.
            
            x = b[0];
            y = b[1];
            
            for(int i=0; i<4; i++) { // 상하좌우를 살펴준다.
                
                int nx = x + dx[i];
                int ny = y + dy[i];
                
                if(nx < 0 || ny < 0 || nx >= n || ny >= m) continue; // 범위 벗어남
                else if(maps[nx][ny] == 0) continue; // 벽임
                else if(maps[nx][ny] == 1) { // 인접 노드가 방문하지 않은 노드라면
                    int[] c = {nx, ny};
                    q.add(c); // Queue에 넣어준다.
                    maps[nx][ny] = maps[x][y] + 1;
                    	// 시작 좌표부터 (nx, ny) 까지 이동한 칸 수를
                        // 점점 누적해서 더해준다.
                        // ( 방문 여부 체크가 되기도 한다. )
                }
            }
        }
        
        return maps[n-1][m-1];
    }

}

 

📌 채점 결과

정확성  테스트
테스트 1 〉	통과 (0.15ms, 81.5MB)
테스트 2 〉	통과 (0.17ms, 77.1MB)
테스트 3 〉	통과 (0.15ms, 72MB)
테스트 4 〉	통과 (0.20ms, 74.2MB)
테스트 5 〉	통과 (0.19ms, 67.4MB)
테스트 6 〉	통과 (0.17ms, 67.1MB)
테스트 7 〉	통과 (0.20ms, 67.6MB)
테스트 8 〉	통과 (0.15ms, 72.3MB)
테스트 9 〉	통과 (0.19ms, 72.5MB)
테스트 10 〉	통과 (0.21ms, 75.3MB)
테스트 11 〉	통과 (0.14ms, 72.7MB)
테스트 12 〉	통과 (0.19ms, 67MB)
테스트 13 〉	통과 (0.19ms, 80.5MB)
테스트 14 〉	통과 (0.21ms, 74.8MB)
테스트 15 〉	통과 (0.14ms, 75.5MB)
테스트 16 〉	통과 (0.16ms, 66.9MB)
테스트 17 〉	통과 (0.19ms, 76.3MB)
테스트 18 〉	통과 (0.19ms, 92.3MB)
테스트 19 〉	통과 (0.17ms, 67.2MB)
테스트 20 〉	통과 (0.17ms, 76.3MB)
테스트 21 〉	통과 (0.16ms, 83.1MB)

효율성  테스트
테스트 1 〉	통과 (8.67ms, 52.6MB)
테스트 2 〉	통과 (3.30ms, 54.1MB)
테스트 3 〉	통과 (5.21ms, 52.7MB)
테스트 4 〉	통과 (4.20ms, 52.5MB)

채점 결과
정확성: 69.9
효율성: 30.1
합계: 100.0 / 100.0

 


[코드 개선]

          for(int i=0; i<4; i++) {
                
                int nx = x + dx[i];
                int ny = y + dy[i];
                
                if(nx < 0 || ny < 0 || nx >= n || ny >= m) continue;
                else if(maps[nx][ny] == 0) continue;
                
                    // maps[nx][ny]가 1이 아닌 경우 모두
                    // 방문할 필요가 없는 노드이므로,
                    // maps[nx][ny]가 0인 경우의 if문을 따로 만들어주지 않아도 될 듯하다.
                    
                else if(maps[nx][ny] == 1) {
                    int[] c = {nx, ny};
                    q.add(c); // Queue에 넣어준다.
                    maps[nx][ny] = maps[x][y] + 1;
                }
            }

 

📌코드

import java.util.*;

class Solution {

    int[][] maps;
    int n = 0;
    int m = 0;
    
    public int solution(int[][] maps) {
        
        n = maps.length;
        m = maps[0].length;
        this.maps = maps;

        int answer = bfs(0,0);
        return (answer == 1) ? -1 : answer;
        // answer이 1이면 방문할 수 없다는 뜻 => -1을 return 한다.
    }
    
    private int bfs(int x, int y) {
        
        // 상, 하, 좌, 우를 살펴주기 위한 배열
        int[] dx = {-1, 1, 0, 0}; // 행 이동
        int[] dy = {0, 0, -1, 1}; // 열 이동

        Queue q = new LinkedList();
        // Queue에는 현재 방문한 좌표로부터
        // 인접한 노드들 중, 방문하지 않은 노드를 넣어줄 것.
        
        int[] a = {x, y}; // 시작점
        q.add(a); // Queue에 넣어준다.
        
        while(!q.isEmpty()) {
            
            int[] b = (int[])q.poll(); // 노드를 꺼내준다.
            
            x = b[0];
            y = b[1];
            
            for(int i=0; i<4; i++) { // 상하좌우를 살펴준다.
                
                int nx = x + dx[i];
                int ny = y + dy[i];
                
                if(nx < 0 || ny < 0 || nx >= n || ny >= m) continue; // 범위 벗어남
                // else if(maps[nx][ny] == 0) continue;
                else if(maps[nx][ny] == 1) { // 인접 노드가 방문하지 않은 노드라면
                    int[] c = {nx, ny};
                    q.add(c); // Queue에 넣어준다.
                    maps[nx][ny] = maps[x][y] + 1;
                    	// 시작 좌표부터 (nx, ny) 까지 이동한 칸 수를
                        // 점점 누적해서 더해준다.
                        // ( 방문 여부 체크가 되기도 한다. )
                }
            }
        }
        
        return maps[n-1][m-1];
    }

}

 

📌 채점 결과

정확성  테스트
테스트 1 〉	통과 (0.18ms, 72MB)
테스트 2 〉	통과 (0.13ms, 77.5MB)
테스트 3 〉	통과 (0.20ms, 73.1MB)
테스트 4 〉	통과 (0.11ms, 70.7MB)
테스트 5 〉	통과 (0.14ms, 72.2MB)
테스트 6 〉	통과 (0.19ms, 74.9MB)
테스트 7 〉	통과 (0.17ms, 75.4MB)
테스트 8 〉	통과 (0.25ms, 74.4MB)
테스트 9 〉	통과 (0.18ms, 74MB)
테스트 10 〉	통과 (0.15ms, 75.1MB)
테스트 11 〉	통과 (0.22ms, 74.6MB)
테스트 12 〉	통과 (0.17ms, 74.6MB)
테스트 13 〉	통과 (0.21ms, 77.6MB)
테스트 14 〉	통과 (0.13ms, 75.5MB)
테스트 15 〉	통과 (0.18ms, 76.6MB)
테스트 16 〉	통과 (0.12ms, 75.5MB)
테스트 17 〉	통과 (0.21ms, 74.9MB)
테스트 18 〉	통과 (0.11ms, 75.4MB)
테스트 19 〉	통과 (0.12ms, 74MB)
테스트 20 〉	통과 (0.12ms, 76.6MB)
테스트 21 〉	통과 (0.12ms, 76.8MB)

효율성  테스트
테스트 1 〉	통과 (8.92ms, 53.8MB)
테스트 2 〉	통과 (2.45ms, 54MB)
테스트 3 〉	통과 (5.75ms, 56.3MB)
테스트 4 〉	통과 (3.79ms, 53.1MB)

채점 결과
정확성: 69.9
효율성: 30.1
합계: 100.0 / 100.0

 

큰... 차이는 없는 듯? 큼큼.


 

[배운 점]

 

📌 배운 것

  1. BFS(넓이 우선 탐색) 를 구현하는 방법
    • Queue를 이용해서 구현할 수 있다.
    • 이해가 안 가서 직접 손으로 작동 과정을 하나하나 그려봤더니 이해가 갔다.