【递归、搜索与回溯】DFS解决FloodFill算法

news2025/4/25 0:25:06

一、经验总结

之前我们已经研究过了BFS解决FloodFill算法:【优选算法】BFS解决FloodFill算法-CSDN博客

DFS只是遍历顺序发生了变化,其他需要注意的点大差不差。


二、相关编程题

2.1 图像渲染

题目链接

733. 图像渲染 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

以给定的初始坐标为起点开始进行DFS,将遍历到的每个位置都修改为新的颜色值(可以防止重复遍历)。需要注意的是,如果修改前后的颜色值相同则会出现重复遍历以至于死循环的结果,所以要进行特殊处理。

编写代码

class Solution {
    int dx[4] = {1, -1, 0, 0};
    int dy[4] = {0, 0, 1, -1};
    int m, n, oldcolor, newcolor;
public:
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) {
        if(image[sr][sc] == color) return image;
        m = image.size(), n = image[0].size();
        newcolor = color, oldcolor = image[sr][sc];
        image[sr][sc] = newcolor;
        DFS(image, sr, sc);
        return image;
    }

    void DFS(vector<vector<int>>& image, int sr, int sc)
    {
        for(int i = 0; i < 4; ++i)
        {
            int x=sr+dx[i], y = sc+dy[i];
            if(x>=0 && x<m && y>=0 && y<n && image[x][y]==oldcolor)
            {
                image[x][y] = newcolor;
                DFS(image, x, y);
            }
        }
    }
};

2.2 岛屿数量

题目链接

200. 岛屿数量 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

遍历grid数组,当遇到未访问的陆地时:

  1. 统计岛屿数量
  2. 以该位置为起点进行深度优先遍历,遍历整个连通块
  3. 将整个连通块中的所有陆地都标记为已访问

编写代码

class Solution {
    int m, n, ret;
    vector<vector<bool>> visited;
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
public:
    int numIslands(vector<vector<char>>& grid) {
        m = grid.size(), n = grid[0].size();
        visited.resize(m, vector<bool>(n, false));
        for(int i = 0; i < m; ++i)
        {
            for(int j = 0; j < n; ++j)
            {
                if(grid[i][j]=='1' && !visited[i][j])
                {
                    ++ret;
                    DFS(grid, i, j);
                }
            }
        }
        return ret;
    }

    void DFS(vector<vector<char>>& grid, int r, int c)
    {
        visited[r][c] = true;
        for(int i = 0; i < 4; ++i)
        {
            int x=r+dx[i], y=c+dy[i];
            if(x>=0 && x<m && y>=0 && y<n && grid[x][y]=='1' && !visited[x][y])
            {
                DFS(grid, x, y);
            }
        }
    }
};

2.3 岛屿的最大面积

题目链接

695. 岛屿的最大面积 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

同上一题基本相同,之不过需要多添加一个变量用于统计每个岛屿的面积。最终返回岛屿的最大面积。

编写代码

class Solution {
    int m, n, ret, tmp;
    vector<vector<bool>> visited;
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        m = grid.size(), n = grid[0].size();
        visited.resize(m, vector<bool>(n, false));
        for(int i = 0; i < m; ++i)
        {
            for(int j = 0; j < n; ++j)
            {
                if(grid[i][j]==1 && !visited[i][j])
                {
                    tmp = 0;
                    DFS(grid, i, j);
                    ret = max(tmp, ret);
                }
            }
        }
        return ret;
    }

    void DFS(vector<vector<int>>& grid, int r, int c)
    {
        ++tmp;
        visited[r][c] = true;
        for(int i = 0; i < 4; ++i)
        {
            int x=r+dx[i], y=c+dy[i];
            if(x>=0 && x<m && y>=0 && y<n && grid[x][y]==1 && !visited[x][y])
            {
                DFS(grid, x, y);
            }
        }
    }
};

2.4 被围绕的区域

题目链接

130. 被围绕的区域 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
    int m, n;
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
public:
    void solve(vector<vector<char>>& board) {
        m = board.size(), n = board[0].size();
        for(int i = 0; i < m; ++i)
        {
            if(board[i][0] == 'O') DFS(board, i, 0);
            if(board[i][n-1] == 'O') DFS(board, i, n-1);
        }
        for(int j = 0; j < n; ++j)
        {
            if(board[0][j] == 'O') DFS(board, 0, j);
            if(board[m-1][j] == 'O') DFS(board, m-1, j);
        }

        for(int i = 0; i < m; ++i)
        {
            for(int j = 0; j < n; ++j)
            {
                if(board[i][j] == 'O') board[i][j] = 'X';
                if(board[i][j] == '.') board[i][j] = 'O';
            }
        }
    }

    void DFS(vector<vector<char>>& board, int r, int c)
    {
        board[r][c] = '.';
        for(int i = 0; i < 4; ++i)
        {
            int x=r+dx[i], y=c+dy[i];
            if(x>=0 && x<m && y>=0 && y<n && board[x][y]=='O')
            {
                DFS(board, x, y);
            }
        }
    }
};

2.5 太平洋大西洋水流问题

题目链接

417. 太平洋大西洋水流问题 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

  1. 统计太平洋水流:以紧邻太平洋的水域(第一行和第一列)为起点逆着水流的方向(>=)进行深度优先遍历,将DFS访问过的水域标记在pacific哈希表。
  2. 统计大西洋水流:以紧邻大西洋的水域(最后一行和最后一列)为起点逆着水流的方向(>=)进行深度优先遍历,将DFS访问过的水域标记在atlantic哈希表。
  3. 找到太平洋和大西洋水流的交集,返回结果。

编写代码

class Solution {
    int m, n;
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    vector<vector<bool>> pacific;
    vector<vector<bool>> atlantic;
public:
    vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
        m = heights.size(), n = heights[0].size();
        pacific.resize(m, vector<bool>(n, false));
        atlantic.resize(m, vector<bool>(n, false));
        vector<vector<int>> ret;
        for(int i = 0; i < m; ++i)
        {
            if(!pacific[i][0]) DFS(heights, pacific, i, 0);
            if(!atlantic[i][n-1]) DFS(heights, atlantic, i, n-1);
        }
        for(int j = 0; j < n; ++j)
        {
            if(!pacific[0][j]) DFS(heights, pacific, 0, j);
            if(!atlantic[m-1][j]) DFS(heights, atlantic, m-1, j);
        }

        for(int i = 0; i < m; ++i)
        {
            for(int j = 0; j < n; ++j)
            {
                if(pacific[i][j] && atlantic[i][j])
                {
                    ret.push_back({i, j});
                }
            }
        }
        return ret;
    }

    void DFS(vector<vector<int>>& heights, vector<vector<bool>>& ocean, int r, int c)
    {
        ocean[r][c] = true;
        for(int i = 0; i < 4; ++i)
        {
            int x=r+dx[i], y=c+dy[i];
            if(x>=0 && x<m && y>=0 && y<n && !ocean[x][y] && heights[x][y]>=heights[r][c])
            {
                DFS(heights, ocean, x, y);
            }
        }
    }
};

2.6 扫雷游戏

题目链接

529. 扫雷游戏 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

见代码

编写代码

class Solution {
    //注意:有8个方向的向量
    int dx[8] = {0, 0, 1, -1, 1, -1, 1, -1}; 
    int dy[8] = {1, -1, 0, 0, 1, -1, -1, 1};
    int m, n;
public:
    vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
        int sr = click[0], sc = click[1];
        if(board[sr][sc] == 'M') //点中雷直接返回
        {
            board[sr][sc] = 'X';
            return board;
        }
        m = board.size(), n = board[0].size();
        DFS(board, sr, sc);
        return board;
    }

    void DFS(vector<vector<char>>& board, int r, int c)
    {
        //统计点击位置周围的地雷数量
        int cnt = 0;
        for(int i = 0; i < 8; ++i)
        {
            int x=r+dx[i], y=c+dy[i];
            if(x>=0 && x<m && y>=0 && y<n && board[x][y]=='M')
                ++cnt;
        }

        if(cnt == 0) //周围没有地雷,向四周继续拓展
        {
            board[r][c] = 'B';
            for(int i = 0; i < 8; ++i)
            {
                int x=r+dx[i], y=c+dy[i];
                if(x>=0 && x<m && y>=0 && y<n && board[x][y]=='E')
                    DFS(board, x, y);
            }
        }
        else //周围有地雷,标记周围地雷的数量
            board[r][c] = cnt+'0';
    }
};

2.7 衣橱整理

题目链接

LCR 130. 衣橱整理 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

编写代码

class Solution {
    int ret;
    int _m, _n, _cnt;
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    bool visited[100][100];
public:
    int wardrobeFinishing(int m, int n, int cnt) {
        _m = m, _n = n, _cnt = cnt;
        DFS(0, 0);
        return ret;
    }

    void DFS(int r, int c)
    {
        visited[r][c] = true;
        ++ret;
        for(int i = 0; i < 4; ++i)
        {
            int x=r+dx[i], y=c+dy[i];
            if(x>=0 && x<_m && y>=0 && y<_n && !visited[x][y] && digit(x)+digit(y)<=_cnt)
                DFS(x, y);
        }
    }

    int digit(int num)
    {
        int sum = 0;
        while(num > 0)
        {
            sum+=num%10;
            num/=10;
        }
        return sum;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1823399.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

少样本学习元学习

基本概念 首先是机器学习&#xff1a; 然后&#xff0c;什么是元学习&#xff08;what is meta learning?) 之前&#xff0c;Component都是让人自己设置的。在Meta Learning中&#xff0c;我们期望它能够自己学出来。 不同的meta learning方法就是想办法去学learning algori…

GoogLeNet(InceptionV3)模型算法

GoogLeNet 团队在给出了一些通用的网络设计准则&#xff0c;以期望在不提高网络参数 量的前提下提升网络的表达能力&#xff1a; 避免特征图 (feature map) 表达瓶颈&#xff1a;从理论上讲&#xff0c;尺寸 (seize) 才包含了相关结构等重要因素&#xff0c;维度(channel) 仅仅…

教师博览杂志教师博览杂志社教师博览编辑部2024年第15期目录

高校教师园地 “心流”融入高职劳动教育课程的思考探究 宫婷婷;柳学知; 4-6 高职院校思政教育与就业创业指导融合机制研究 袁晓旭; 7-9 职教社助力乡村人才振兴的实践探索和功能定位——以江西省为例 涂恬; 10-12 育人之道《教师博览》投稿&#xff1a;cn7kantouga…

这家来自内蒙古的物流企业,用另一种方式减碳超500吨

2016年&#xff0c;多蒙德实业集团整合旗下物流及运销板块&#xff0c;组建成立了内蒙古多蒙德科技有限公司&#xff08;以下简称“多蒙德”&#xff09;&#xff0c;整合互联网、大数据及智慧物流为一体&#xff0c;自主研发多蒙达网络货运平台及多个供应链智慧系统&#xff0…

对话分析数据:揭秘企业销售场景的隐形金矿

在数字化浪潮席卷全球的今天&#xff0c;企业对于数据的依赖愈发显著。尤其是在销售领域&#xff0c;数据不仅能够帮助企业精准定位市场&#xff0c;还能在竞争激烈的商海中为企业指明航向。每一个电话、每一次会议、每一段对话&#xff0c;都是企业宝贵的数据资产。然而&#…

机器学习二分类数据集预处理全流程实战讲解

本文概述 本文对weatherAUS数据集进行缺失值分析并剔除高缺失特征&#xff0c;合理填补剩余缺失值&#xff0c;利用相关性筛选关键特征&#xff0c;采用多种机器学习模型&#xff08;如逻辑回归、随机森林等&#xff09;在80%训练集上训练&#xff0c;并在20%测试集上预测明日降…

NG32031单片机串口初始化

目录 1. 串口基础 2. 串口配置步骤 3. N32G031串口初始化示例 3.1开启时钟 3.2 配置GPIO 3.3 配置USART 3.4 使能中断&#xff08;如果需要&#xff09; 3.5. 示例代码 4. 调试和验证 5. 注意事项 6. 额外功能 NG32G031单片机的串口&#xff08;UART&#xff09;通常…

【硬件模块】SSD1306 OLED屏幕(含GD32ESP32驱动代码)

OLED屏幕 最近在写GD32的文章&#xff0c;之前STM32有OLED屏幕来展示数据&#xff0c;ESP32可以直接打印到电脑屏幕上&#xff0c;GD32的话手上就没有办法了。 虽然是可以直接把STM32的OLED屏幕的驱动代码改改移植到GD32上面&#xff0c;不过想了想干脆写一个文章来说说如何驱…

苍穹外卖笔记-13-导入地址簿功能代码、用户下单、订单支付

文章目录 1. 导入地址簿功能代码1.1 需求分析和设计1.1.1 产品原型1.1.2 接口设计1.1.3 表设计 1.2 代码导入1.2.1 Mapper层1.2.2 Service层1.2.3 Controller层 1.3 功能测试 2. 用户下单2.1 需求分析和设计2.1.1 产品原型2.1.2 接口设计2.1.3 表设计 2.2 代码开发2.2.1 DTO设计…

「动态规划」买卖股票的最佳时机,如何处理多笔交易?

188. 买卖股票的最佳时机 IVhttps://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/description/ 给你一个整数数组prices和一个整数k&#xff0c;其中prices[i]是某支给定的股票在第i天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成k笔交易。…

嵌入式linux中内存管理基本原理

各位开发者,大家好,今天主要给大家分享一下,如何使用linux系统中的内存管理。 前面我们学习了很多Linux内存方面的知识,比如:虚拟地址空间,进程空间,内存映射,页表机制等,我们学了这么多知识,似乎对Linux内存似懂非懂,为什么会出现这样的问题?原因在于我们缺…

关于FPGA对 DDR4 (MT40A256M16)的读写控制 2

关于FPGA对 DDR4 &#xff08;MT40A256M16&#xff09;的读写控制 2 语言 &#xff1a;Verilg HDL EDA工具&#xff1a;ISE、Vivado、Quartus II 关于FPGA对 DDR4 &#xff08;MT40A256M16&#xff09;的读写控制 2一、引言二、DDR4的简介四、DDR4 SDRAM状态框图 关键词&#x…

Java多线程学习笔记

文章目录 1. 引言1.1 多线程的重要性 2. 什么是多线程2.1 线程的定义和基本概念2.2 线程与进程的区别 3. 创建线程的方式3.1 继承Thread类3.2 实现Runnable接口&#xff0c;重写run方法3.3 实现Runnable接口&#xff0c;重写call方法3.4 匿名内部类创建Thread子类对象3.5 使用匿…

ROS中Twist消息类型

Twist消息类型在Robot Operating System (ROS)中是一个常见的数据结构&#xff0c;主要用于描述物体的线性速度和角速度。这种消息类型在ROS的geometry_msgs包中定义&#xff0c;常用于机器人运动控制&#xff0c;尤其是当需要向机器人发布速度指令时。 Twist消息由两个Vector…

21.1 文件-文件的重要性、ioutil包

1. 文件的重要性 文件的本质就是硬盘中的数据&#xff0c;包括各种程序、文档、多媒体甚至系统配置。 各种类UNIX操作系统的一个重要特征就是将一切皆视为文件。 可以象访问文件一样访问键盘、打印机等硬件设备可以象访问文件一样访问管道、套接字等内核资源 各种类UNIX操作…

网络基础OSI国际互联

这里所指的网络是计算机网络&#xff0c;由许许多多的不同的网络设备以及电子设备构建的一个ip的网络&#xff0c;这个就是工作对象 网络是随着计算机的出现&#xff0c;军事沟通 出现的问题&#xff1a;物理层设备&#xff0c;总线&#xff0c;共享设备&#xff0c;会产生冲突…

用 C 语言实现求补码的运算

缘起 前两天程序中需要求一堆参数的补码&#xff0c;一时犯懒&#xff0c;想从CSDN上搜一个勉强能用的代码借鉴一下&#xff0c;结果几乎没有搜到一个靠谱的&#xff01;这种求补码的操作&#xff0c;用脚趾头想想也应该知道要用C或者C的位运算来实现呀。结果搜到的一些实现方…

MyBatis-Plus整合达梦数据库

文章目录 1. 环境准备2. 创建Spring Boot项目3. 引入依赖4. 配置数据源5. 配置MyBatis-Plus6. 创建实体类7. 创建Mapper接口8. 创建Service类9. 创建Controller类10. 创建Mapper XML文件11. 测试12. 进一步优化12.1 配置分页插件12.2 配置乐观锁插件13. 总结🎉欢迎来到Java学…

vue+elementui+springboot图片上传

1、前端代码 <template><div><el-uploadclass"avatar-uploader"action"http://localhost:8081/ch06/demo/uploadAvatar":show-file-list"false":on-success"handleAvatarSuccess":before-upload"beforeAvatarUpl…

SIGMOD 2024 | 时空数据(Spatial-Temporal)和时间序列(Time Series)论文总结

SIGMOD2024于6月9号-6月14号正在智利圣地亚戈举行&#xff08;Santiago Chile&#xff09; 本文总结了SIGMOD 2024有关时间序列&#xff08;time series&#xff09;,包括时序数据库&#xff0c;查询优化等内容。以及时空数据&#xff08;spatial-temporal data&#xff09;的…