(Graph, Medium) Pacific Atlantic Water Flow

송재호·2025년 2월 17일
0

https://leetcode.com/problems/pacific-atlantic-water-flow/description/

이런 문제는 재밌어 보인다.

2중 for문 돌면서 특정 [r][c] 인덱스에 있는 정점으로부터 출발해
Pacific과 Atlantic에 모두 닿을 수 있는지 체크하면 될 것 같다.

그럼 Pacific에 닿는다는 것과 Atlantic에 닿는다는 것을 정리할 필요가 있다.
heights는 m x n 이라고 했으므로

visitPacific - [0][c] 또는 [r][0]
visitAtlantic - [m-1][c] 또는 [r][n-1]

코드는 어렵지 않으니 별다른 말 없이 첨부

class Solution {

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

    public List<List<Integer>> pacificAtlantic(int[][] heights) {
        List<List<Integer>> answer = new ArrayList<>();

        int m = heights.length;
        int n = heights[0].length;

        for (int i=0; i<m; i++) {
            for (int j=0; j<n; j++) {
                if (canFlow(heights, i, j, m, n)) {
                    List<Integer> coordinate = new ArrayList<>();
                    coordinate.add(i);
                    coordinate.add(j);
                    answer.add(coordinate);
                }
            }
        }
        return answer;
    }

    public boolean canFlow(int[][] heights, int r, int c, int m, int n) {
        boolean visitPacific = false;
        boolean visitAtlantic = false;

        boolean[][] visited = new boolean[m][n];

        // int[] - index 0: r, 1: c
        Queue<int[]> que = new LinkedList<>();
        que.offer(new int[]{ r, c });

        while (!que.isEmpty()) {
            int[] coordinate = que.poll();
            int x = coordinate[0];
            int y = coordinate[1];

            visited[x][y] = true;
            int currentHeight = heights[x][y];
            
            if (x == 0 || y == 0) {
                visitPacific = true;
            }
            if ((x == m - 1) || (y == n - 1)) {
                visitAtlantic = true;
            }
            if (visitPacific && visitAtlantic) {
                return true;
            }

            for (int i=0; i<4; i++) {
                int nextX = x + dx[i];
                int nextY = y + dy[i];
                boolean possibleRange = nextX >= 0 && nextX < m && nextY >= 0 && nextY < n;
                if (possibleRange) {
                    boolean possibleHeight = currentHeight >= heights[nextX][nextY];
                    if (possibleHeight && !visited[nextX][nextY]) {
                        que.offer(new int[]{ nextX, nextY });
                    }
                }
            }
        }
        return false;
    }
}

이 방식대로 했을 때 동작은 하지만 2개 케이스에서 timeout이 발생한다.
아무래도 모든 좌표를 한 번 씩 다 탐색하면서 이어나가기 때문인 것 같다.

고민을 좀 하다가 솔루션 참고했는데
가능성이 있는 4가지 케이스로 먼저 맵을 만들어 두는 것 같다.
pacific 인접 - first row, first column
atlantic 인접 - last row, last column

이렇게 하는 경우 확실하게 닿을 수 있는 위치부터 탐색을 이어가기 때문에
내 기존 코드처럼 아무데도 못 가는 케이스를 굳이 돌아볼 필요가 없어진다.

교훈: 탐색 시작점에 대해 충분히 고민해보자.

(코드 수정해서 여기 붙여넣기)

profile
식지 않는 감자

0개의 댓글