首页 > 其他分享 >代码随想录 | 图论 797. 所有可能的路径(dfs) ,200. 岛屿数量 (dfs)200. 岛屿数量 (bfs) ,并查集,1971. 寻找图中是否存在路径

代码随想录 | 图论 797. 所有可能的路径(dfs) ,200. 岛屿数量 (dfs)200. 岛屿数量 (bfs) ,并查集,1971. 寻找图中是否存在路径

时间:2024-04-05 22:24:05浏览次数:16  
标签:200 int 路径 father dfs length grid public

797. 所有可能的路径
https://leetcode.cn/problems/all-paths-from-source-to-target/description/

List<List<Integer>> res;
    List<Integer> path;
    public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
        res = new ArrayList<>();
        path = new ArrayList<>();
        path.add(0);
        dfs(graph,0);
        return res;
    }
//x是已经选择的节点  回溯中往往是要选择的节点
    public void dfs(int[][] graph,int x){
        if (x == graph.length - 1){
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < graph[x].length; i++) {
            path.add(graph[x][i]);
            dfs(graph,graph[x][i]);
            path.remove(path.size()-1);
        }
    }

总结:dfs,深度优先遍历,跟回溯类似,但是dfs是先把0节点加进去,再进入dfs函数进行递归流程,参数x代表着已经加入的节点,我们这层dfs要找的加的是x的下一个点。而递归往往是在这层backtracking中传的参数包含于这层要加入的节点(往往参数传个foe循环起始值)。
**bfs **
广度优先适合于解决两点之间最短路径问题
200. 岛屿数量 (dfs)
https://leetcode.cn/problems/number-of-islands/description/

boolean[][] visited;
    int top;
    int bottom;
    int left;
    int right;
    public int numIslands(char[][] grid) {
        visited = new boolean[grid.length][grid[0].length];
        top = 0;
        bottom = grid.length - 1;
        left = 0;
        right = grid[0].length - 1;
        int count = 0;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (visited[i][j] == false && grid[i][j] == '1'){
                    count++;
                    dfs(grid,i,j);
                }
            }
        }
        return count;
    }
    public void dfs(char[][] grid,int i,int j){
        if (i < top || i > bottom || j < left || j > right){
            return;
        }
        if (visited[i][j] == true || grid[i][j] == '0'){
            return;
        }
        visited[i][j] = true;
        for (int k = 0; k < 4; k++) {
            switch (k){
                case 0:{
                    dfs(grid,i-1,j);
                    break;
                }
                case 1:{
                    dfs(grid,i+1,j);
                    break;
                }
                case 2:{
                    dfs(grid,i,j-1);
                    break;
                }
                case 3:{
                    dfs(grid,i,j+1);
                    break;
                }
            }
        }
    }

总结:遍历所有点,如果是陆地而且未被遍历过,就从这个点开始走一次dfs。
**200. 岛屿数量 (bfs) **
https://leetcode.cn/problems/number-of-islands/

boolean[][] visited;
    int[][] move = {{-1,0},{1,0},{0,-1},{0,1}};
    int top;
    int bottom;
    int left;
    int right;
    public int numIslands(char[][] grid) {
        visited = new boolean[grid.length][grid[0].length];
        int count = 0;
        top = 0;
        bottom = grid.length - 1;
        left = 0;
        right = grid[0].length - 1;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (visited[i][j] == false && grid[i][j] == '1'){
                    count++;
                    bfs(grid,i,j);
                }
            }
        }
        return count;
    }
    public void bfs(char[][] grid,int x,int y){
        Deque<int[]> deque = new ArrayDeque<>();
        deque.offer(new int[]{x,y});
        visited[x][y] = true;
        while (!deque.isEmpty()){
            int[] cur = deque.poll();
            int curx = cur[0];
            int cury = cur[1];
            for (int i = 0; i < 4; i++) {
                int newx = curx + move[i][0];
                int newy = cury + move[i][1];
                if (newx < top || newx > bottom || newy < left || newy > right)continue;
                if (visited[newx][newy] == false && grid[newx][newy] == '1'){
                    deque.offer(new int[]{newx,newy});
                    visited[newx][newy] = true;
                }
            }
        }
    }

总结:bfs广度优先,广度优先不是递归了,是队列,每次进队节点就立即标记为访问过。
并查集

并查集常用来解决连通性问题。
大白话就是当我们需要判断两个元素是否在同一个集合里的时候,我们就要想到用并查集。

并查集模板

并查集模板
int[] father;
    // 并查集初始化
    public void init() {
        for (int i = 0; i < father.length; i++) {
            father[i] = i;
        }
    }

    // 并查集里寻根的过程
    public int find(int u) {
        if (u == father[u]) {
            return u;
        } else {
            father[u] = find(father[u]);
            return father[u];
        }
    }

    // 判断 u 和 v是否找到同一个根
    public boolean isSame(int u, int v) {
        u = find(u);
        v = find(v);
        return u == v;
    }

    // 将v->u 这条边加入并查集
    public void join(int u, int v) {
        u = find(u); // 寻找u的根
        v = find(v); // 寻找v的根
        if (u == v) return; // 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回

        father[v] = u;
    }

总结:并查集用来检查两个玩意在不在一个集合里,可能是两个点之间有没有路径。并查集要有init(),join(),find(),isSame(),这个模板是路径压缩的模板,每次join边的时候不是直接让v指向u,而是让v的根指向u的根,这样并查集就是一颗扁平的树,层数很低。
1971. 寻找图中是否存在路径
https://leetcode.cn/problems/find-if-path-exists-in-graph/description/

int[] father;
    public boolean validPath(int n, int[][] edges, int source, int destination) {
        father = new int[n];
        init();
        for (int i = 0; i < edges.length; i++) {
            int u = edges[i][0];
            int v = edges[i][1];
            join(u,v);
        }
        return isSame(source,destination);
    }
    public void init(){
        for (int i = 0; i < father.length; i++) {
            father[i] = i;
        }
    }
    public void join(int u,int v){
        u = find(u);
        v = find(v);
        if (u == v) return;
        father[v] = u;
    }
    public int find(int u){
        if (father[u] == u) {
            return u;
        }else {
            father[u] = find(father[u]);
            return father[u];
        }
    }
    public boolean isSame(int u,int v){
        u = find(u);
        v = find(v);
        return u == v;
    }

总结:并查集的应用罢了。

标签:200,int,路径,father,dfs,length,grid,public
From: https://www.cnblogs.com/jeasonGo/p/18116287

相关文章

  • P1435 [IOI2000] 回文字串
    题目:链接:https://www.luogu.com.cn/problem/P1435观察到:在里面插入字符不会影响外面的配对所以以dp[i][j]记录字符串s下标从i到j变化到回文串步数,那么递推公式:if(s[i]==s[j])dp[i][j]=dp[i+1][j-1];elsedp[i][j]=min(dp[i+1][j],dp[i][j-1])+1;就是说如果最外面能......
  • 蓝桥杯_省_21B_E_路径(c++)
    题目描述小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图中的最短路径。小蓝的图由2021个结点组成,依次编号1至2021。对于两个不同的结点a,b,如果a和b的差的绝对值大于21,则两个结点之间没有边相连;如果a和b的差的绝对值小于等于21,则两个点之间......
  • 4. 飞机降落-dfs
    4.飞机降落-蓝桥云课(lanqiao.cn)230100101010100220301020101020201020#include<bits/stdc++.h>#defineintlonglong#defineendl'\n'usingnamespacestd;structplane{intt,d,l;}p[12];intn;//pan数组用来判断当前飞机降落了么......
  • matlab练习程序(Pure Pursuit路径跟踪)
    当时写stanley就实现了,贴上来记录一下。方法示意图:控制率公式:其中L为轴距,e为横向误差,v为车辆速度,lambda和c为控制参数。算法步骤如下:1.根据当前定位结果找到路径最邻近点。2.计算该点与定位结果横向误差e。3.根据控制率公式计算出前轮转角。4.将前轮转角转化为航向......
  • P9058 [Ynoi2004] rpmtdq 题解
    Description给定一棵有边权的无根树,需要回答一些询问。定义\(\texttt{dist(i,j)}\)代表树上点\(i\)和点\(j\)之间的距离。对于每一组询问,会给出\(l,r\),你需要输出\(\min(\texttt{dist(i,j)})\)其中\(l\leqi<j\leqr\)。\(n\leq2\times10^5\),\(q\leq10^6\),\(1\l......
  • P4329 [COCI2006-2007#1] Bond
    原题链接题解二进制dpetc:令\(dp[00110]\)代表前两个任务选23两个人出战的最大成功率则\(dp[00110]=max(dp[00010]+a[3][2],dp[00100]+a[2][3])\)code#include<bits/stdc++.h>usingnamespacestd;doublea[25][25]={0};doubledp[1<<22]={0};intcal(intnow){......
  • 蓝桥杯,省赛,dfs专题,地宫取宝,小朋友崇拜圈,飞机降落
    #include<bits/stdc++.h>usingnamespacestd;intn,m,k;inta[55][55];//输入所给数组值所分配的内存空间intdp[55][55][15][15];//开创记忆化的存储空间//因为只进行向下走和向右走,所有写成这个样子,不明白的可以在了解以下笛卡尔积,向下是x轴,向右是y轴(一般情况下)int......
  • dask读取hdfs文件时报错connect hdfs error
    问题详情:/arrow/cpp/src/arrow/filesystem/hdfs.cc:51:Failedtodisconnecthdfsclient:IOError:HDFShdfsFS::Disconnectfailed,errno:9(Badfiledescriptor)Traceback(mostrecentcalllast):File"/home/tdops/fucheng.pan/ray-code/read.py",line......
  • P2285 [HNOI2004] 打鼹鼠
    题目:链接:https://www.luogu.com.cn/problem/P2285这题感觉如果想不到递推关系可能会很麻烦,因为我之前想到的关系就是用dp存:包含三个维度:times,x,y,即dp[times][x][y]来存,然后递推。但是如果把dp看作是以p结尾的抓到的耗子数量时就会方便很多同时要注意,每次到一个点的时候先立为1......
  • 开发一个react组件包的时候,组件包里的路径是不是最好使用相对路径../不建议使用别名@
    在开发React组件包时,关于路径的选择,是否使用相对路径(如../)或路径别名(如@),取决于具体项目需求、团队规范以及个人偏好。两者都有其适用场景和优缺点,下面分别进行讨论:使用相对路径(如../):优点:通用性:相对路径直接基于文件系统结构,无需额外配置即可被大多数开发环境和构建工具理......