← Graphs

Pacific Atlantic Water Flow

Medium
Python
def pacific_atlantic(heights):
    m,n=len(heights),len(heights[0])
    pac,atl=set(),set()
    def dfs(r,c,visited,prev):
        if (r,c) in visited or r<0 or r>=m or c<0 or c>=n or heights[r][c]<prev: return
        visited.add((r,c))
        for dr,dc in [(1,0),(-1,0),(0,1),(0,-1)]:
            dfs(r+dr,c+dc,visited,heights[r][c])
    for r in range(m): dfs(r,0,pac,heights[r][0]); dfs(r,n-1,atl,heights[r][n-1])
    for c in range(n): dfs(0,c,pac,heights[0][c]); dfs(m-1,c,atl,heights[m-1][c])
    return [[r,c] for r in range(m) for c in range(n) if (r,c) in pac and (r,c) in atl]
Java
public List<List<Integer>> pacificAtlantic(int[][] heights){
    int m=heights.length,n=heights[0].length;
    boolean[][] pac=new boolean[m][n],atl=new boolean[m][n];
    for(int r=0;r<m;r++){dfs(heights,pac,r,0,0);dfs(heights,atl,r,n-1,0);}
    for(int c=0;c<n;c++){dfs(heights,pac,0,c,0);dfs(heights,atl,m-1,c,0);}
    List<List<Integer>> res=new ArrayList<>();
    for(int r=0;r<m;r++) for(int c=0;c<n;c++)
        if(pac[r][c]&&atl[r][c]) res.add(Arrays.asList(r,c));
    return res;
}
void dfs(int[][] h,boolean[][] vis,int r,int c,int prev){
    if(r<0||r>=h.length||c<0||c>=h[0].length||vis[r][c]||h[r][c]<prev) return;
    vis[r][c]=true;
    for(int[] d:new int[][]{{1,0},{-1,0},{0,1},{0,-1}}) dfs(h,vis,r+d[0],c+d[1],h[r][c]);
}

Key Insight

Reverse DFS from borders. Python set of tuples vs Java boolean 2D array.

Python → Java Differences

  • Python set of tuples vs Java 2D boolean array
  • Python list comprehension for result
  • Reverse DFS from borders identical
Python
def pacific_atlantic(heights):
    m,n=len(heights),len(heights[0])
    pac,atl=set(),set()
    def dfs(r,c,visited,prev):
        if (r,c) in visited or r<0 or r>=m or c<0 or c>=n or heights[r][c]<prev: return
        visited.add((r,c))
        for dr,dc in [(1,0),(-1,0),(0,1),(0,-1)]:
            dfs(r+dr,c+dc,visited,heights[r][c])
    for r in range(m): dfs(r,0,pac,heights[r][0]); dfs(r,n-1,atl,heights[r][n-1])
    for c in range(n): dfs(0,c,pac,heights[0][c]); dfs(m-1,c,atl,heights[m-1][c])
    return [[r,c] for r in range(m) for c in range(n) if (r,c) in pac and (r,c) in atl]
Java
public List<List<Integer>> pacificAtlantic(int[][] heights){
    int m=heights.length,n=heights[0].length;
    boolean[][] pac=new boolean[m][n],atl=new boolean[m][n];
    for(int r=0;r<m;r++){dfs(heights,pac,r,0,0);dfs(heights,atl,r,n-1,0);}
    for(int c=0;c<n;c++){dfs(heights,pac,0,c,0);dfs(heights,atl,m-1,c,0);}
    List<List<Integer>> res=new ArrayList<>();
    for(int r=0;r<m;r++) for(int c=0;c<n;c++)
        if(pac[r][c]&&atl[r][c]) res.add(Arrays.asList(r,c));
    return res;
}
void dfs(int[][] h,boolean[][] vis,int r,int c,int prev){
    if(r<0||r>=h.length||c<0||c>=h[0].length||vis[r][c]||h[r][c]<prev) return;
    vis[r][c]=true;
    for(int[] d:new int[][]{{1,0},{-1,0},{0,1},{0,-1}}) dfs(h,vis,r+d[0],c+d[1],h[r][c]);
}

Algorithm Steps

1. DFS from each border
2. Find cells reachable from both