【经典LeetCode算法题目专栏分类】【第9期】深度优先搜索DFS与并查集:括号生成、岛屿问题、扫雷游戏

简介: 【经典LeetCode算法题目专栏分类】【第9期】深度优先搜索DFS与并查集:括号生成、岛屿问题、扫雷游戏

DFS

括号生成

DFS
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        def DFS(left, right, s):
            if left == n and right == n:
                res.append(s)
                return
            if left < n:
                DFS(left+1,right,s+'(')
            if right < left:
                DFS(left,right + 1,s+')')
        res = []
        DFS(0,0,'')
        return res
BFS
class Node:
    def __init__(self, left, right, s):
        self.left = left
        self.right = right
        self.s = s
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        # BFS写法
        res = []
        if n == 0:
            return res
        queue = [Node(n,n,'')]
        while queue:
            node = queue.pop(0)
            if node.left == 0 and node.right == 0:
                res.append(node.s)
            if node.left > 0:
                queue.append(Node(node.left-1, node.right, node.s+'('))
            if node.right > 0 and node.right > node.left:
                queue.append(Node(node.left, node.right-1, node.s+')'))
        return res
# 写法2:
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        # BFS写法
        res = []
        if n == 0:
            return res
        queue = [(n,n,'')]
        while queue:
            node = queue.pop(0)
            if node[0] == 0 and node[1] == 0:
                res.append(node[2])
            if node[0] > 0:
                queue.append((node[0]-1, node[1], node[2]+'('))
            if node[1] > 0 and node[1] > node[0]:
                queue.append((node[0], node[1]-1, node[2]+')'))
        return res

通常搜索几乎都是用深度优先遍历(回溯算法)。

广度优先遍历,得自己编写结点类,显示使用队列这个数据结构。深度优先遍历的时候,就可以直接使用系统栈,在递归方法执行完成的时候,系统栈顶就把我们所需要的状态信息直接弹出,而无须编写结点类和显示使用栈。

将BFS写法中的pop(0)改为pop()即为深度优先的迭代形式。

对比迭代的BFS写法与递归的DFS写法,可以看到,BFS其实是将DFS的参数当做队列中的一个元素来进行处理罢了,其他的与DFS没有什么区别。

并查集

岛屿问题

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        self.m = len(grid)
        self.n = len(grid[0])
        res = 0
        for i in range(self.m):
            for j in range(self.n):
                if grid[i][j] == '1':
                    self.sink(i,j,grid)
                    res += 1
        return res
    
    def sink(self, i, j, grid):
        grid[i][j] = '0'
        for ni,nj in [(i-1,j),(i+1,j),(i,j-1),(i,j+1)]:
            if 0<=ni<self.m and 0<=nj<self.n and grid[ni][nj] == '1':
                self.sink(ni,nj,grid)

扫雷游戏

# DFS
class Solution:
    def updateBoard(self, board: List[List[str]], click: List[int]) -> List[List[str]]:
        # DFS
        i, j = click
        row, col = len(board), len(board[0])
        if board[i][j] == "M":
            board[i][j] = "X"
            return board
        # 计算空白快周围的雷数量
        def cal(i, j):
            res = 0
            for x in [1, -1, 0]:
                for y in [1, -1, 0]:
                    if x == 0 and y == 0: continue
                    if 0 <= i + x < row and 0 <= j + y < col and board[i + x][j + y] == "M": res += 1
            return res
        def dfs(i, j):
            num = cal(i, j)
            if num > 0:
                board[i][j] = str(num)
                return
            board[i][j] = "B"
            for x in [1, -1, 0]:
                for y in [1, -1, 0]:
                    if x == 0 and y == 0: continue
                    nxt_i, nxt_j = i + x, j + y
                    if 0 <= nxt_i < row and 0 <= nxt_j < col and board[nxt_i][nxt_j] == "E": dfs(nxt_i, nxt_j)
        dfs(i, j)
        return board
# BFS
class Solution:
    def updateBoard(self, board: List[List[str]], click: List[int]) -> List[List[str]]:
        i, j = click
        row, col = len(board), len(board[0])
        if board[i][j] == "M":
            board[i][j] = "X"
            return board
        # 计算空白块周围的雷数目
        def cal(i, j):
            res = 0
            for x in [1, -1, 0]:
                for y in [1, -1, 0]:
                    if x == 0 and y == 0: continue
                    if 0 <= i + x < row and 0 <= j + y < col and board[i + x][j + y] == "M": res += 1
            return res
        def bfs(i, j):
            queue = [(i,j)]
            while queue:
                i, j = queue.pop(0)
                num = cal(i, j)
                if num > 0:
                    board[i][j] = str(num)
                    continue
                board[i][j] = "B"
                for x in [1, -1, 0]:
                    for y in [1, -1, 0]:
                        if x == 0 and y == 0: continue
                        nxt_i, nxt_j = i + x, j + y
                        if nxt_i < 0 or nxt_i >= row or nxt_j < 0 or nxt_j >= col: continue
                        if board[nxt_i][nxt_j] == "E":
                            queue.append((nxt_i, nxt_j))
                            board[nxt_i][nxt_j] = "B"  # 主要是用于标识该点已经被访问过,防止后续重复的添加相同的‘E’点
        bfs(i, j)
        return board


相关文章
|
10天前
|
分布式计算 算法 Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本文讲解了两道经典的图论问题:**岛屿数量(LeetCode 200)** 和 **腐烂的橘子(LeetCode 994)**,分别通过 DFS/BFS 实现。在“岛屿数量”中,利用深度或广度优先搜索遍历二维网格,标记连通陆地并计数;“腐烂的橘子”则采用多源 BFS,模拟腐烂传播过程,计算最短时间。两者均需掌握访问标记技巧,是学习网格搜索算法的绝佳实践。
37 1
|
10天前
|
Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本篇博客详细解析了三道经典的动态规划问题:198. 打家劫舍(线性状态转移)、279. 完全平方数与322. 零钱兑换(完全背包问题)。通过 Go 语言实现,帮助读者掌握动态规划的核心思想及其实战技巧。从状态定义到转移方程,逐步剖析每道题的解法,并总结其异同点,助力解决更复杂的 DP 问题。适合初学者深入理解动态规划的应用场景和优化方法。
28 0
|
5月前
|
机器学习/深度学习 算法 数据可视化
利用SVM(支持向量机)分类算法对鸢尾花数据集进行分类
本文介绍了如何使用支持向量机(SVM)算法对鸢尾花数据集进行分类。作者通过Python的sklearn库加载数据,并利用pandas、matplotlib等工具进行数据分析和可视化。
486 70
|
3月前
|
机器学习/深度学习 资源调度 算法
基于入侵野草算法的KNN分类优化matlab仿真
本程序基于入侵野草算法(IWO)优化KNN分类器,通过模拟自然界中野草的扩散与竞争过程,寻找最优特征组合和超参数。核心步骤包括初始化、繁殖、变异和选择,以提升KNN分类效果。程序在MATLAB2022A上运行,展示了优化后的分类性能。该方法适用于高维数据和复杂分类任务,显著提高了分类准确性。
|
8月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
84 0
|
10月前
|
算法 搜索推荐
LeetCode第75题颜色分类
文章介绍了LeetCode第75题"颜色分类"的解法,通过双指针技术对数组中的0、1和2进行排序,避免了传统的排序算法,提供了一种时间复杂度为O(n)的高效解决方案。
LeetCode第75题颜色分类
|
4月前
|
存储 算法 iOS开发
【狂热算法篇】并查集:探秘图论中的 “连通神器”,解锁动态连通性的神秘力量(通俗易懂版)
【狂热算法篇】并查集:探秘图论中的 “连通神器”,解锁动态连通性的神秘力量(通俗易懂版)
|
7月前
|
存储 算法 Java
leetcode算法题-有效的括号(简单)
【11月更文挑战第5天】本文介绍了 LeetCode 上“有效的括号”这道题的解法。题目要求判断一个只包含括号字符的字符串是否有效。有效字符串需满足左括号必须用相同类型的右括号闭合,并且左括号必须以正确的顺序闭合。解题思路是使用栈数据结构,遍历字符串时将左括号压入栈中,遇到右括号时检查栈顶元素是否匹配。最后根据栈是否为空来判断字符串中的括号是否有效。示例代码包括 Python 和 Java 版本。
145 4
|
9月前
|
算法 JavaScript 前端开发
第一个算法项目 | JS实现并查集迷宫算法Demo学习
本文是关于使用JavaScript实现并查集迷宫算法的中国象棋demo的学习记录,包括项目运行方法、知识点梳理、代码赏析以及相关CSS样式表文件的介绍。
第一个算法项目 | JS实现并查集迷宫算法Demo学习
|
9月前
|
机器学习/深度学习 人工智能 算法
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
文本分类识别系统。本系统使用Python作为主要开发语言,首先收集了10种中文文本数据集("体育类", "财经类", "房产类", "家居类", "教育类", "科技类", "时尚类", "时政类", "游戏类", "娱乐类"),然后基于TensorFlow搭建CNN卷积神经网络算法模型。通过对数据集进行多轮迭代训练,最后得到一个识别精度较高的模型,并保存为本地的h5格式。然后使用Django开发Web网页端操作界面,实现用户上传一段文本识别其所属的类别。
286 1
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台

热门文章

最新文章