【Leetcode】top 100 图论

这篇具有很好参考价值的文章主要介绍了【Leetcode】top 100 图论。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基础知识补充

1.图分为有向图和无向图,有权图和无权图;

2.图的表示方法:邻接矩阵适合表示稠密图,邻接表适合表示稀疏图;

   邻接矩阵:

【Leetcode】top 100 图论,leetcode,图论,算法

   邻接表:

【Leetcode】top 100 图论,leetcode,图论,算法

基础操作补充

1.邻接矩阵:

class GraphAdjacencyMatrix:
    def __init__(self, num_vertices):
        self.num_vertices = num_vertices
        self.matrix = [[0] * num_vertices for _ in range(num_vertices)]

    def add_edge(self, start, end):       # 无向图
        self.matrix[start][end] = 1
        self.matrix[end][start] = 1

2.邻接表:

from collections import defaultdict

class GraphAdjacencyList:
    def __init__(self):
        self.graph = defaultdict(list)

    def add_edge(self, start, end):        # 无向图
        self.graph[start].append(end)
        self.graph[end].append(start)

3.图的遍历:

# 深度优先搜索(DFS):
# 从上到下,递归或栈实现
def dfs(graph, start, visited=None):
    if visited is None:
        visited = set()
    visited.add(start)
    print(start, end=" ")
    for neighbor in graph[start]:
        if neighbor not in visited:
            dfs(graph, neighbor, visited)

# 广度优先搜索(BFS):
# 从左到右,队列实现
from collections import deque

def bfs(graph, start):
    visited = set()
    queue = deque([start])
    visited.add(start)
    while queue:
        current = queue.popleft()
        print(current, end=" ")
        for neighbor in graph[current]:
            if neighbor not in visited:
                queue.append(neighbor)
                visited.add(neighbor)

 题目
200 岛屿数量

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。

 方法一:深度优先搜索 DFS
若当前点是岛屿时,向上下左右四个点做深度搜索;终止条件:越界;当前是水;

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        def dfs(nums, x, y):
            if x<0 or x>len(nums)-1: return 
            if y<0 or y>len(nums[0])-1: return 
            if nums[x][y] =='0':return 
            else:
                nums[x][y] = '0'    # 必须先置0,否则会在两个'1'间连续递归至超过栈长
                dfs(nums, x-1, y)
                dfs(nums, x+1, y)
                dfs(nums, x, y-1)
                dfs(nums, x, y+1)
            
        cnt = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == '1':
                    dfs(grid, i, j)
                    cnt += 1
        return cnt

方法二:广度优先搜索 BFS

若当前点是岛屿时,将其上下左右四个点都加入队列;终止条件:越界;当前是水;

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        def bfs(nums, x, y):
            queue = [(x, y)]
            while queue:
                (x, y) = queue.pop(0)
                if x<0 or x>len(nums)-1: continue 
                elif y<0 or y>len(nums[0])-1: continue 
                elif nums[x][y] =='0':continue 
                else:
                    nums[x][y] = '0'    # 必须先置0,否则会在两个'1'间连续递归至超过栈长
                    queue.append((x-1, y))
                    queue.append((x+1, y))
                    queue.append((x, y-1))
                    queue.append((x, y+1))
        
        cnt = 0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j] == '1':
                    bfs(grid, i, j)
                    cnt += 1
        return cnt
 994 腐烂的橘子

在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一:

  • 值 0 代表空单元格;
  • 值 1 代表新鲜橘子;
  • 值 2 代表腐烂的橘子。

每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1 。

第一次遍历将所有新鲜橘子腐烂,统计腐烂次数;第二次遍历统计是否还有剩余的新鲜橘子;(若初始就不含有新鲜橘子呢?)

一次遍历统计新鲜橘子数量的同时记录腐烂橘子的位置(队列);

遍历队列,若当前位置是腐烂橘子则将其上下左右四个点入队,若当前位置是新鲜橘子则将新鲜橘子数量-1再将其上下左右四个点入队;需要将处理过的位置的值置为0,代表不再处理;

class Solution(object):
    def orangesRotting(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        
        cnt, queue = 0, []
        m, n = len(grid), len(grid[0])
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1:
                    cnt += 1
                elif grid[i][j] == 2:
                    queue.append([i,j])

        if cnt == 0: return 0

        time, stack = -1, []
        while queue:
            [x, y] = queue.pop(0)
            if -1<x<m and -1<y<n and grid[x][y]:
                if grid[x][y] == 1: cnt -= 1
                grid[x][y] = 0            # 不再处理这个点
                stack.append([x-1, y])
                stack.append([x+1, y])
                stack.append([x, y-1])
                stack.append([x, y+1])
            if not queue and stack:
                queue = stack
                time += 1 
                stack = []

        return -1 if cnt else time

计算遍历深度用BFS

207 课程表

你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程  bi 。

  • 例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。

请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。

方法一:广度优先搜索

from collections import deque
from collections import defaultdict

class Solution(object):
    def canFinish(self, numCourses, prerequisites):
        """
        :type numCourses: int
        :type prerequisites: List[List[int]]
        :rtype: bool
        """
        degree = [0]*numCourses    
        maps = defaultdict(list)   
        queue = deque()
        for cur, pre in prerequisites:
            degree[cur] += 1                      # 统计每门课的先修课程数
            maps[pre].append(cur)                 # 记录基础课和对应的进阶课
        for i in range(numCourses):
            if degree[i] == 0: queue.append(i)    # 无先修课程(基础课)时入队
        count = 0
        while queue:
            course = queue.popleft()
            count += 1
            for i in maps[course]:                # 将以course为基础课的进阶课的先修课数-1
                degree[i] -= 1
                if degree[i] == 0:                # 已修完全部基础课
                    queue.append(i)  
        return count == numCourses

方法二:深度优先搜索

class Solution(object):
    def canFinish(self, numCourses, prerequisites):
        """
        :type numCourses: int
        :type prerequisites: List[List[int]]
        :rtype: bool
        """
        degree = [0]* numCourses
        maps = defaultdict(list)
        def dfs(i):
            if degree[i]==-1: return False    # degree[i]==-1 表示会陷入循环
            if degree[i]==1: return True      # degree[i]==1 表示能完成课 
            degree[i]=-1                      # 防止 1-0-1 转回来的情况
            for pre in maps[i]:               # 遍历每门基础课
                if not dfs(pre): return False
            degree[i]=1                       # 该门课可以完成
            return True
        
        for cur, pre in prerequisites:        # 记录先修课和其基础课程
            maps[cur].append(pre)
        for i in range(numCourses):           # 遍历每门课
            dfs(i)
        return sum(degree) == numCourses      # 若每门课都完成应该全为1
208 实现Trie(前缀树)

Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。

请你实现 Trie 类:

  • Trie() 初始化前缀树对象。
  • void insert(String word) 向前缀树中插入字符串 word 。
  • boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。
  • boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。

核心:使用「边」来代表有无字符,使用「点」来记录是否为「单词结尾」以及「其后续字符串的字符是什么」

【Leetcode】top 100 图论,leetcode,图论,算法

class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_end = False

class Trie(object):
    def __init__(self):
        self.root = TrieNode()

    def insert(self, word):
        """
        :type word: str
        :rtype: None
        """
        node = self.root
        for c in word:
            if c not in node.children:
                node.children[c] = TrieNode()
            node = node.children[c]
        node.is_end = True

    def searchPrefix(self, word):
        node = self.root
        for c in word:
            if c not in node.children: return None
            node = node.children[c]
        return node

    def search(self, word):
        """
        :type word: str
        :rtype: bool
        """
        node = self.searchPrefix(word)
        return node is not None and node.is_end

    def startsWith(self, prefix):
        """
        :type prefix: str
        :rtype: bool
        """
        node = self.searchPrefix(prefix)
        return node is not None
 额外补充

flood fill 带你学习Flood Fill算法与最短路模型 - 时间最考验人 - 博客园 (cnblogs.com)文章来源地址https://www.toymoban.com/news/detail-846209.html

到了这里,关于【Leetcode】top 100 图论的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Leetcode Top 100 Liked Questions(序号75~104)

     题意:红白蓝的颜色排序,使得相同的颜色放在一起,不要用排序 哈希 代码 Runtime 4 ms Beats 28.23% Memory 8.3 MB Beats 9.95% Dutch National Flag Problem荷兰国旗问题; 代码 计数排序 Runtime 0 ms Beats 100% Memory 8.3 MB Beats 41.44% 感觉和我之前做的差不多 代码 双指针 Runtime 0 ms Beats 100% Memory

    2024年02月10日
    浏览(33)
  • Leetcode Top 100 Liked Questions(序号53~74)

    题意:一个数组,找到和最大的子串 我记得好像On的动态规划来做的?但是想不起来了,先死做,用的 前缀和——TLE超时 那就只能想想dp怎么做了 假设dp[i]表示的是以 i 为右端点的最大的子串,dp[0]是自己; i=1时,如果dp[0]小于0,dp[1]=nums[1],否则dp[1]=dp[0]+nums[1] i=2时,如果

    2024年02月12日
    浏览(39)
  • 【LeetCode热题100】【图论】腐烂的橘子

    题目描述:994. 腐烂的橘子 - 力扣(LeetCode) 腐烂的橘子会污染周围的橘子,要求多少轮扩散才能把全部橘子污染,这就相当于滴墨水入清水,会扩散,其实就是广度遍历,看看遍历多少层可以遍历完可以遍历的 先遍历一次橘子,记录下腐烂橘子的位置和新鲜橘子的数目,然

    2024年04月23日
    浏览(41)
  • 【leetcode100-051到054】【图论】四题合集

    【岛屿数量】 给你一个由  \\\'1\\\' (陆地)和  \\\'0\\\' (水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外,你可以假设该网格的四条边均被水包围。 思路: 很经典也很基础的图搜

    2024年01月23日
    浏览(43)
  • 【LeetCode 热题 100】图论 专题(bfs,拓扑排序,Trie树 字典树)

    from: https://leetcode.cn/studyplan/top-100-liked/ bfs 具有 边权为1 的最短路性质 拓扑排序,入度 Trie树, 高效存储 字符串【见鬼,不知道为什么写错,需要掌握熟练度】 dfs 写法,比较简洁 bfs 写法,有最短路性质 bfs 具有 边权为1 的最短路性质 拓扑排序 模板题 数组写法,简洁,需

    2024年02月13日
    浏览(52)
  • TOP100 图论

    给你一个由  \\\'1\\\' (陆地)和  \\\'0\\\' (水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外,你可以假设该网格的四条边均被水包围。 示例 1: 示例 2: 提示: m == grid.length n == g

    2024年02月19日
    浏览(37)
  • 浅谈图论——迪杰斯特拉算法(leetcode例题,C++演示)

    如果你想问这个世界上什么算法是最牛逼的?博主是回答不上来的。但是,如果你问博主 什么数据结构是最牛逼 ?博主个人认为 图是最牛逼的数据结构 。因为很多的问题,都可以用图这种数据结构来表示。链表、树这种数据结构博主认为可以看成一种 特殊的图 。所以,博

    2024年02月20日
    浏览(81)
  • 每天一道leetcode:1192. 查找集群内的关键连接(图论&困难&tarjan算法)

    力扣数据中心有 n 台服务器,分别按从 0 到 n-1 的方式进行了编号。它们之间以 服务器到服务器 的形式相互连接组成了一个内部集群,连接是无向的。用 connections 表示集群网络, connections[i] = [a, b] 表示服务器 a 和 b 之间形成连接。任何服务器都可以直接或者间接地通过网络

    2024年02月12日
    浏览(50)
  • 【LeetCode 热题 100】矩阵 专题(大多原地算法,需要一定思维)

    解题思路 在 代码注释中!

    2024年02月15日
    浏览(51)
  • Java算法_ 杨辉三角(LeetCode_Hot100)

    题目描述:题目描述:给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中,每个数是它左上方和右上方的数的和。 获得更多?算法思路:代码文档,算法解析的私得。 运行效果 完整代码

    2024年02月13日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包