递归、搜索与回溯-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);
                }
            }
        }
    }
}
相关推荐
谎言西西里19 小时前
LeetCode 热题100 --- 双指针专区
算法
五岳21 小时前
分库分表数据源ShardingSphereDataSource的Connection元数据误用问题分析
java·mysql·爬坑
带刺的坐椅21 小时前
迈向 MCP 集群化:Solon AI (支持 Java8+)在解决 MCP 服务可扩展性上的探索与实践
java·ai·llm·solon·mcp
鼠爷ねずみ21 小时前
SpringCloud前后端整体开发流程-以及技术总结文章实时更新中
java·数据库·后端·spring·spring cloud
代码or搬砖21 小时前
String字符串
android·java·开发语言
leo__5201 天前
基于两步成像算法的聚束模式SAR MATLAB实现
开发语言·算法·matlab
前端小白在前进1 天前
力扣刷题:在排序数组中查找元素的第一个和最后一个位置
数据结构·算法·leetcode
AM越.1 天前
Java设计模式详解--装饰器设计模式(含uml图)
java·设计模式·uml
5980354151 天前
【java工具类】小数、整数转中文大写
android·java·开发语言