递归、搜索与回溯-FloodFill:33.太平洋大西洋水流问题

题目链接:417. 太平洋大西洋水流问题(中等)

算法原理:

解法:DFS

Java算法:

java 复制代码
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 王洋
 * Date: 2025-10-09
 * Time: 22:26
 */
class Solution {
    //417. 太平洋大西洋水流问题
    //自己写的,不能用hash表的原因:有高度一样的,无法锁定坐标,其余一遍过
    //豆包帮我改出来的:要用两个boolean数组分别记录,否则第二个就记录不上了
    int m,n;
    int[] dx=new int[]{0,0,1,-1};
    int[] dy=new int[]{1,-1,0,0};
    List<List<Integer>> ret;
    List<Integer> tmp;
    boolean[][] vis1;//统计流向太平洋的
    boolean[][] vis2;//统计流向大西洋的
    //Map<Intger,Integer> hash;
    public List<List<Integer>> pacificAtlantic(int[][] heights) {
        ret=new ArrayList<>();
        //hash=new HashMap<>();
        m=heights.length;n=heights[0].length;
        vis1=new boolean[m][n];
        vis2=new boolean[m][n];
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                //统计能流向太平洋的
                if(!vis1[i][j]&&(i==0||j==0)){
                    vis1[i][j]=true;
                    //记录当前值
                    int prev=heights[i][j];
                    dfs(heights,i,j,prev,vis1);
                }
                //统计能流向大西洋的
                if(!vis2[i][j]&&(i==m-1||j==n-1)){
                    vis2[i][j]=true;
                    //记录当前值
                    int prev=heights[i][j];
                    dfs(heights,i,j,prev,vis2);
                }
            }
        }
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(vis1[i][j]&&vis2[i][j]){
                    tmp=new ArrayList<>();//每次进入都要重新统计
                    tmp.add(i);
                    tmp.add(j);
                    ret.add(tmp);
                }
            }
        }
        // for(<Map.Entry<Integer,Integer> entry:entries){
        //     if(entry.getKey()>1){
        //         tmp=new ArrayList<>();//每次进入都要重新统计
        //         tmp.add(entry.getKey());
        //         tmp.add(entry.getValue());
        //         ret.add(tmp);
        //     }
        // }
        return ret;
    }
    public void dfs(int[][] heights,int i,int j,int prev,boolean[][] vised){
        for(int k=0;k<4;k++){
            int x=i+dx[k],y=j+dy[k];
            if(x<m&&y<n&&x>=0&&y>=0&&!vised[x][y]&&heights[x][y]>=prev){
                vised[x][y]=true;
                //hash.put(heights[x][y],hash.getOrDefalut(heights[x][y],0)+1);
                dfs(heights,x,y,heights[x][y],vised);
            }
        }
    }


    class Solution {
        //自己写的,不能用hash表的原因:有高度一样的,无法锁定坐标,其余一遍过
        //豆包帮我改出来的:要用两个boolean数组分别记录,否则第二个就记录不上了
        //吴小哲的跟我的差不多,主要不同点在标记方法上,他用n的复杂度,我用的n²的复杂度+dfs不用记录之前的数
        //直接height[x][y]跟height[i][j]比较就行
        int m,n;
        int[] dx=new int[]{0,0,1,-1};
        int[] dy=new int[]{1,-1,0,0};
        List<List<Integer>> ret;
        List<Integer> tmp;
        boolean[][] vis1;//统计流向太平洋的
        boolean[][] vis2;//统计流向大西洋的
        //Map<Intger,Integer> hash;
        public List<List<Integer>> pacificAtlantic(int[][] heights) {
            ret=new ArrayList<>();
            //hash=new HashMap<>();
            m=heights.length;n=heights[0].length;
            vis1=new boolean[m][n];
            vis2=new boolean[m][n];
            // for(int i=0;i<m;i++){
            //     for(int j=0;j<n;j++){
            //         //统计能流向太平洋的
            //         if(!vis1[i][j]&&(i==0||j==0)){
            //             vis1[i][j]=true;
            //             //记录当前值
            //             int prev=heights[i][j];
            //             dfs(heights,i,j,prev,vis1);
            //         }
            //         //统计能流向大西洋的
            //         if(!vis2[i][j]&&(i==m-1||j==n-1)){
            //             vis2[i][j]=true;
            //             //记录当前值
            //             int prev=heights[i][j];
            //             dfs(heights,i,j,prev,vis2);
            //         }
            //     }
            // }

            //吴小哲的标记方法,我感觉挺好的,直接时间复杂度n²降到n

            //流向太平洋的
            for(int i=0;i<m;i++){vis1[i][0]=true;dfs(heights,i,0,vis1);}
            for(int j=0;j<n;j++){vis1[0][j]=true;dfs(heights,0,j,vis1);}
            //流向大西洋的
            for(int i=0;i<m;i++){vis2[i][n-1]=true;dfs(heights,i,n-1,vis2);}
            for(int j=0;j<n;j++){vis2[m-1][j]=true;dfs(heights,m-1,j,vis2);}

            for(int i=0;i<m;i++){
                for(int j=0;j<n;j++){
                    if(vis1[i][j]&&vis2[i][j]){
                        tmp=new ArrayList<>();//每次进入都要重新统计
                        tmp.add(i);
                        tmp.add(j);
                        ret.add(tmp);
                    }
                }
            }
            // for(<Map.Entry<Integer,Integer> entry:entries){
            //     if(entry.getKey()>1){
            //         tmp=new ArrayList<>();//每次进入都要重新统计
            //         tmp.add(entry.getKey());
            //         tmp.add(entry.getValue());
            //         ret.add(tmp);
            //     }
            // }
            return ret;
        }
        public void dfs(int[][] heights,int i,int j,boolean[][] vised){
            for(int k=0;k<4;k++){
                int x=i+dx[k],y=j+dy[k];
                if(x<m&&y<n&&x>=0&&y>=0&&!vised[x][y]&&heights[x][y]>=heights[i][j]){
                    vised[x][y]=true;
                    //hash.put(heights[x][y],hash.getOrDefalut(heights[x][y],0)+1);
                    dfs(heights,x,y,vised);
                }
            }
        }
    }
}
相关推荐
计算机程序设计小李同学1 天前
基于 Spring Boot + Vue 的龙虾专营店管理系统的设计与实现
java·spring boot·后端·spring·vue
LiZhen7981 天前
SpringBoot 实现动态切换数据源
java·spring boot·mybatis
周航宇JoeZhou1 天前
JB2-7-HTML
java·前端·容器·html·h5·标签·表单
Not Dr.Wang4221 天前
自动控制系统稳定性研究及判据分析
算法
VT.馒头1 天前
【力扣】2722. 根据 ID 合并两个数组
javascript·算法·leetcode·职场和发展·typescript
ffqws_1 天前
A*算法:P5507 机关 题解
算法
JZC_xiaozhong1 天前
多系统权限标准不统一?企业如何实现跨平台统一权限管控
java·大数据·微服务·数据集成与应用集成·iam系统·权限治理·统一权限管理
执着2591 天前
力扣hot100 - 108、将有序数组转换为二叉搜索树
算法·leetcode·职场和发展
2501_901147831 天前
学习笔记:单调递增数字求解的迭代优化与工程实践
linux·服务器·笔记·学习·算法
AI科技星1 天前
张祥前统一场论核心场方程的经典验证-基于电子与质子的求导溯源及力的精确计算
线性代数·算法·机器学习·矩阵·概率论