【LeetCode】797 and 1189(图论基础)

图论基础

图的逻辑结构和具体实现

⼀幅图是由节点和边构成的,逻辑结构如下:
在这里插入图片描述
什么叫「逻辑结构」?就是说为了⽅便研究,我们把图抽象成这个样⼦。
该逻辑结构等价于「多叉树」,其中每个节点可以定义为:

/* 图节点的逻辑结构 */
class Vertex {
	int id;
	Vertex[] neighbors;
}

但为了方便和易于理解,通常使用邻接表和邻接矩阵来实现:
在这里插入图片描述
「邻接表」很直观,我把每个节点 x 的邻居都存到⼀个列表⾥,然后把 x 和这个列表关联起来,这样就可以通过⼀个节点 x 找到它的所有相邻节点。
「邻接矩阵」则是⼀个⼆维布尔数组,我们权且称为 matrix,如果节点 x 和 y 是相连的,那么就把 matrix[x][y] 设为 true(上图中绿⾊的⽅格代表 true)。如果想找节点 x 的邻居,去扫⼀圈 matrix[x][…] 就⾏了。
两种实现方式的优缺点为,对于邻接表,好处是占⽤的空间少。但是,邻接表⽆法快速判断两个节点是否相邻。所以说,使⽤哪⼀种⽅式实现图,要看具体情况。
好了,对于「图」这种数据结构,能看懂上⾯这些就绰绰够⽤了。下⾯通过实例来看看所有数据结构都逃不过的问题:遍历。

797. 所有可能的路径

在这里插入图片描述
在这里插入图片描述
解法:深度优先搜索
有关图的遍历,可以参考多叉树的遍历框架,
在这里插入图片描述
图和多叉树最⼤的区别是,图是可能包含环的,你从图的某⼀个节点开始遍历,有可能⾛了⼀圈⼜回到这个节点。
所以,如果图包含环,遍历框架就要⼀个 visited 数组进⾏辅助:
在这里插入图片描述
由于该题是无环的,因此可以直接套用多叉树的遍历框架,进行深度优先遍历求解即可。

class Solution:
    def allPathsSourceTarget(self, graph: List[List[int]]) -> List[List[int]]:
        result = []
        n = len(graph) - 1
        # path 用于维护递归过程中经过的路径
        def traverse(value, path):
            nonlocal result
            nonlocal n
            # 遍历到终点,添加路径
            if value == n:
                result.append(path + [value])
                return
        	# 添加节点到当前路径
            path.append(value)
            # 递归每个相邻节点
            for num in graph[value]:
                traverse(num, path)
            # 从路径中移除节点
            path.pop()
        traverse(0, [])
        return result

1189. "气球"的最大数量(每日一题)

在这里插入图片描述
解法:数学
统计"a",“b”,“l”,“o”,“n"的出现次数。由于"l”,"o"在"balloon"出现2次,需要对统计次数整除2才为其能够拼凑次数。最后取所有单词拼凑次数的最小值作为结果。

class Solution:
    def maxNumberOfBalloons(self, text: str) -> int:
        count = {
            "a": 0,
            "b": 0,
            "l": 0,
            "o": 0,
            "n": 0
        }

        for char in text:
            if char in count:
                count[char] += 1
            
        count['l'] //= 2
        count['o'] //= 2
        return min(count.values())

总结

最后总结⼀下,图的存储⽅式主要有邻接表和邻接矩阵,⽆论什么花⾥胡哨的图,都可以⽤这两种⽅式存储。
在笔试中,最常考的算法是图的遍历,和多叉树的遍历框架是⾮常类似的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值