Skip to content

图论算法(六)

About 3627 wordsAbout 12 min

graph图论

2024-03-28

一、基础遍历

思考:

  • 如何思考递归?(不要一来就看细节,将原问题划分成子问题)
  • 为什么需要使用递归?
  • 为什么递归是对的?(数学归纳法,当n=1时成立;假设n=m...)
  • 计算机是怎么执行递归过程的?(通过压栈和出栈实现递归)

问:一直有个疑问,啥时候需要有返回值,啥时候不需要返回值?

  • 看你怎么写递归,如果是自顶向下的话,可以没有返回值;如果是自底向上的话,就一定要有返回值。

思考结果:

  • 我们在循环的时候,就是在重复的执行同样一份代码;我们将原问题划分成相同的子问题,在计划原问题和子问题的时候应该也使用同样一套代码
  • 将原问题划分成更小的子问题,再把更小的子问题划分成在小的子问题,这个过程就是递归中的递,不断递下去,总会有尽头,就是递归的边界条件。
  • 从递归的边界条件返回的时候,就是递归中的归。非边界条件。
  • 在递归的时候,除了把节点传下去,还可以把路径上的节点个数也传下去。

image-20250329000623669

  • 递归怎么知道return到那个节点上呢?在递归的时候,计算机没有丢弃上一个节点,而是保存下来了,那用什么数据结构存储呢?用栈存储,递归的递就是压栈的过程,递归的归就是出栈的过程。

1.1、DFS基础

104. 二叉树的最大深度(20250326更新)

这道题从2020年开始就有提交,到现在2025年,终于有了不一样的理解。

我们需要知道什么是二叉树的最大深度,就是从跟节点到最下方叶子节点经过的节点个数为二叉树的最大深度。

所以我们只需要遍历一次,记录最大深度就可以了。DFS和BFS都可以。

灵神-自顶向下

404. 左叶子之和(20250327更新)

只有从左节点回到根节点的时候,我们才能确认是左节点,这个时候同时在判断是否是叶子节点(左右节点都为空)就可以了。

java

实现力扣树构建的方式,比如给出[1,2,3,4,5], [3,9,20,null,null,15,7] 能够知道是一颗什么样子的树。

543. 二叉树的直径(20250327)

二叉树的直径就是任意两个节点的最大路径,我们只需要求到根节点左子树的最大高度,加上右子树的最大高度再加一就是我们需要的结果。

java

114. 二叉树展开为链表(20250328更新)

labuladong算法可视化面板

Java

116. 填充每个节点的下一个右侧节点指针(20250328更新)

traver(l.left, l.right), traver(r.left, r.right), traver(l.right, r.left) ???

Java

112. 路径总和(20250329更新)

给你二叉树的根节点root和一个表示目标和的整数targetSum。判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标targetSum。如果存在,返回true;否则,返回false。

自顶向下的DFS方法求解路径总和

129. 求根节点到叶节点数字之和(20250329更新)

给你一个二叉树的根节点root,树中每个节点都存放一个0-9的数字,每条从根到叶子节点的路径代表一个数字:

  • 例如,从根节点到叶子节点的路径1-2-3表示数字123.

计算从根节点到叶子节点生成的所有数字之和。

自顶向下的深度遍历解决《求根节点到叶子节点数字之和》

1448. 统计二叉树中好节点的数目(20250329)

给你一颗根为root的二叉树,请你返回二叉树中好节点的数目。

好节点X定义为:从根节点到节点X所经过的节点中,没有任何节点的值大雨X的值。

灵神-自顶向下

1.2、BFS基础

104. 二叉树的最大深度(20250326更新)

这个也可以写成BFS的形式。

BFS有三种写法,一种就是最简单的,把节点存进去然后取出来遍历,但是这一种没有办法记录层数;第二种就是通过一个for循环来记录每一层,相当于每层的权重是1;还有第三种就是节点维护自己的层级(权重)。

二叉树的递归/层序遍历

Java

二、其他

1791. 找出星型图的中心节点

有一个无向的星型图,由 n 个编号从 1 到 n 的节点组成,星型图有一个中心节点,并且恰有 n-1 条边将中心节点与其他节点连接起来。

给你一个二维整数数组 edges,其中 edges[i]=[ui, vi]表示在节点之间存在一条边,请你找出返回 edges 所有表示星型图的中心节点。

根据题意,中心节点必然出现在所有的 edges[i]中,根据第一条边,判断里面的两个数据是否在后面边里面,如果在的话,就是中心节点,否则就不是中心节点。

因为题目给出 n 是大于等于 3 的,必定是大于两个节点的。

class Solution {
    public int findCenter(int[][] edges) {
        int a = edges[0][0], b =edges[0][1];
        if(a == edges[1][0] || a == edges[1][1]){
            return a;
        }
        else{
            return b;
        }
    }
}

1557. 可以到达所有点的最少点数目

给你一个 有向无环图, n 个节点编码为 0 到 n-1, 以及一个变数组 edges,其中 edges[i] = [from, to], 表示一条从 from 到 to 的有向边。

找到最小的点集使得从这些点出发能到达图中所有的点,题目保证解存在且唯一。

你可以以任何顺序返回这些节点的编号。

最小的点集使得能够到达图的所有点,这里我们只需要找到入度为 0 的节点就是题目的解。

构建 java 列表并初始化的方式

1、List<Integer> list = Arrays.asList(1,2,3);

2、List<Integer> lit = new ArrayList<>(Arrays.asList(1,1,3));

3、List<String> lit = new ArrayList<>(Collections.singletonList("a", "b"));

图论基础及遍历算法

学习 labuladong 关于图相关的理论和知识点。

图的话和多叉树遍历类似,需要防止遍历的时候形成环,使用数据 visit 来表示每个节点是否被访问过。

图的存储的话有两种方式,一个是领接表,一个是领接矩阵,分别定义如下:

// 邻接表
List<Integer>[] graph;

// 邻接矩阵
boolean[][] graph;

如果是带权图的话,邻接表存储的时候顺便把权重也存起来,邻接矩阵的话,每个坐标存的就是权重,不是 true 或者 false。

度(degree),入度(indegree), 出度(outdegree)

矩阵(martix),顶点(vertex)

图的遍历模版:

LCR 110. 所有可能的路径

给定一个有 n 个节点的有向无环图,用二维数组 graph 表示,请找到所有从 0 到 n-1 的路径并输出。

graph 的第 i 个数组中的单元都表示有向图 i 号节点所能够到达的下一个节点。

从 0 节点开始遍历图,将到达 n-1 的路径保存下来。

547. 省份数量

这个题就是求无向图中的连通域的个数,直接 dfs/bfs。

题目给出的 isConnected 是邻接矩阵的存储方式。

Changelog

Last Updated: 3/30/25, 4:18 PMView All Changelog
  • feat(wiki): algo: 算法总结

    On 3/30/25

求求了,快滚去学习!!!

求求了求求了,快去学习吧!

【题单】贪心算法

不知道方向的时候,可以多看看书,书会给你指明下一步该干什么,加油!