LeetCode系列-DFS深度优先遍历

DFS

详细介绍

秉承不撞南墙不回头的道理,标记当前节点,从当前节点出发采用递归的方式访问相邻的节点,一直到底。
递归出口:1.已经访问完从当前节点一直相邻的所有节点为止、2.超出边界、此当前节点已经被访问。
当前节点已遍历结束,对下一个未被标记的节点进行同样的上述操作。

实例

1. 剑指offer13机器人的运动范围

在这里插入图片描述
解题思路
深度优先遍历走所有的格子
判断 超出方格边界、走到之前访问的格子、数位之和超过k 则直接返回 return 0
否则 一直向下或者向右遍历,且递归一次成功的个数+1

class Solution:
    def movingCount(self, m: int, n: int, k: int) -> int:
        # 计算位之和
        def wei(x):
            sum = 0
            while x:
                sum += x%10
                x = x // 10
            return sum
        # 深度优先遍历
        def dfs(i,j):
            # 超出方格边界
            if i >= m or j >= n:
                return 0
            # 走到之前访问过的位置
            if (i, j) in res:
                return 0
            # 障碍物,位数之和大于k
            weii, weij = wei(i), wei(j)
            if weii + weij > k:
                return 0
            # 成功格子的下标
            res.add((i,j))
            # 向下或者向右移动,成功个数+1
            return 1 + dfs(i+1, j) + dfs(i, j+1)
        res = set()
        count = dfs(0, 0) 
        return count #return len(count)也可以

2. 695岛屿的最大面积

在这里插入图片描述
在这里插入图片描述
解题思路
深度优先,当单元格为1时传入DFS,然后递归前后左右,同时在走过的格子标为0避免重复计算,递归一圈长度+1

class Solution:
    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        # 典型深度优先,当单元格为1时传入DFS,然后递归前后左右,同时在走过的格子标为0避免重复计算,递归一圈长度+1
        m, n = len(grid),len(grid[0])
        def dfs(i, j):
            # 递归出口:i、j超出边界、单元格不等于1
            if i < 0 or i >= m or j < 0 or j >= n or grid[i][j]==0:
                return 0
            grid[i][j] = 0
            # 递归当前单元格的上下左右
            return 1 + dfs(i+1, j) + dfs(i-1, j) + dfs(i, j+1) + dfs(i, j-1)
        res = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j]==1:
                    res = max(res, dfs(i, j))
        return res

3. 200. 岛屿数量

在这里插入图片描述
解题思路
当找到一个岛屿,递归周围的所有相邻岛屿,并将岛屿制为0,count+=1,然后找下一堆岛屿

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        m, n = len(grid), len(grid[0])
        def dfs(i, j):
            # 递归出口:超过边界、不是岛屿
            if i < 0 or i >= m or j < 0 or j >= n or grid[i][j]=='0':
                return 0
            # 将岛屿制为0避免重复搜索
            grid[i][j] = '0'
            # 递归当前岛屿的上下左右
            dfs(i + 1, j)
            dfs(i, j + 1)
            dfs(i - 1, j)
            dfs(i, j - 1)
        count = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] == '1':
                    dfs(i, j)
                    count += 1
        return count

4. 剑指 Offer 12. 矩阵中的路径

在这里插入图片描述
在这里插入图片描述
解题思路
DFS+回溯,与以往DFS不同的是,一轮中把走过的点清除但是到下一轮循环之前要恢复原来的值即回溯

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        m,n = len(board),len(board[0])
        def dfs(i,j,k):
            # 递归出口:超出边界、当前值不同
            if i < 0 or i >= m or j < 0 or j >= n or board[i][j] != word[k]:
                return False
            if k == len(word) - 1:
                return True
            board[i][j] = '' # 把这轮走过的点清除避免重复
            # 递归上下左右,并且连续正确的长度+1,res代表是否成功的标记
            res = dfs(i+1,j,k+1) or dfs(i-1,j,k+1) or dfs(i,j+1,k+1) or dfs(i,j-1,k+1)
            # 回溯,表示在下一轮循环中还需要原来的标记
            board[i][j] = word[k]
            return res
        for i in range(m):
            for j in range(n):
                # 如果dfs返回true则存在,k表示连续正确的长度
                if dfs(i,j,0):
                    return True
        return False

题目来源:https://leetcode.cn/problemset/all/

解题来源:作者的leetcode题解
同时参考了很多大佬的答案解析,得到了很多比较棒的思路
自己做笔记记录使用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值