class Solution:
    def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
        """ tc O(MN)  sc O(MN) M: rows N: cols
        where is Pacific rigion:  [0,x] or [y,0]
                 Atlantic region   [xx,n-1] or [m-1,yy]
        updating res condition: when start from (i,j) can go both pacific and atlantic region
        main idea: set global state variable a_seen and p_seen ( can be set or bucket list), start from         edges next to ocean (flood from the ocean)  do dfs(); in the end check coordinates wich both pass both oceans  
        
        1. initialize state set for both oceans 
        2. from four edges, do dfs to update ocean region status  
        3. return result 
        within dfs function:
            1. check if visited, and update seen 
            2. check unvisited neighbours, for those with [!!!!lower] value than current, proceed with next level recursion 
        """
        m,n = len(heights),len(heights[0])
        a_seen = set()
        p_seen = set()
        def dfs(i,j,seen):
            if (i,j) in seen:  # here can be ignored and add checker for new pos only since caller has verified (i,j) is not visited 
                return 
            seen.add((i,j))

            for dx,dy in ([1,0],[-1,0],[0,1],[0,-1]):
                new_i = i + dx
                new_j = j + dy
                # if nei can go to cur_pos, nei should have same flag status 
                #if x < 0 or y <0 or x >= rows or y >= cols or heights[x][y]< heights[i][j]:
                #  continue  will optimize
                if 0 <= new_i < m and 0 <= new_j < n and heights[i][j] <= heights[new_i][new_j]: # and (new_i,new_j) not in seen  
                    dfs(new_i,new_j,seen)
                    
        for row in range(m):
            dfs(row,0,p_seen)
            dfs(row,n-1,a_seen)
        for col in range(n):
            dfs(0,col,p_seen)
            dfs(m-1,col,a_seen)
            
        return list(a_seen&p_seen)