洪水灌溉算法 + 总结

news2025/3/31 15:32:39

文章目录

  • floodfill算法
  • 图像渲染
    • 题解
    • 代码
  • 岛屿数量
    • 题解
    • 代码
  • 岛屿的最大面积
    • 题解
    • 代码
  • 被围绕的区域
    • 题解
    • 代码
  • 太平洋大西洋水流问题
    • 题解
    • 代码
  • 扫雷游戏
    • 题解
    • 代码
  • 衣橱整理
    • 题解
    • 代码
  • 总结

floodfill算法

1. 寻找相同性质的联通块,可以使用dfs或者bfs解决,比如把1连通块的周围都修改为2

在这里插入图片描述

图像渲染

题目链接
在这里插入图片描述

题解

1.我们通过将以sr,sc为起始点,将该点周围的联通块都修改为color
2. 全局变量: p记录要修改的联通块的值,m,n矩阵的长和宽,坐标dx,dy向上下左右方向搜索
3. 细节处理:如果起始点(sr,sc)就是color的值,不需要修改直接返回矩阵,因为该点周围已经被渲斓为color颜色了,这样会无限渲斓下去,因为是同一个值,未改变,具体可以看实例二

在这里插入图片描述

代码

class Solution 
{
public:
    int m,n;
    int p; 
    // 渲斓一个联通块
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color)  
    {
        p = image[sr][sc];
        m = image.size(),n = image[0].size();
        // 避免死循环,该点和该点周围一圈都是目标颜色,就无限进入循环中
       if(image[sr][sc] == color) return image;

        dfs(image,sr,sc,color);
        
        return image;
    }
    
    int dx[4] = {-1,1,0,0};
    int dy[4] = {0,0,-1,1};

    void dfs(vector<vector<int>>& image,int i,int j,int color)
    {
        image[i][j] = color;
        for(int k = 0;k < 4;k++)
        {
            // 用例一:不会到达值是0的位置
            int x = dx[k] + i,y = dy[k] + j;
            if(x >= 0 && x < m && y >= 0 && y < n && image[x][y] == p)
            {
                dfs(image,x,y,color);
            }
        }
    }
};

岛屿数量

题目链接
在这里插入图片描述

题解

1. 计算联通块的数量,只要左右上下相邻的1就是一个连通块
2. 需要使用标记数组标记已经走过的1,避免重复到达同一个1,或者把搜索过的1都修改为0,建议使用第一种,第二中如果想要恢复成原来的数组比较困难

代码

class Solution 
{
public:
    int m,n;
    int count;// 记录联通块的个数
    int numIslands(vector<vector<char>>& grid) 
    {
       // 将遇到的一块陆地的联通块都变为海水,联通块加一,下次再遇到陆地依次类推
       m = grid.size(),n = grid[0].size();
       for(int i = 0;i < m;i++)
       {
        for(int j = 0;j < n;j++)
        {
            if(grid[i][j] == '1')
            {
                dfs(grid,i,j);
                count++;
            } 
        }
       }     
       return count;  
    }
    
    int dx[4] = {0,0,-1,1};
    int dy[4] = {-1,1,0,0};

    void dfs(vector<vector<char>>& grid,int i,int j)
    {
        for(int k = 0;k < 4;k++)
        {
            int x = dx[k] + i,y = dy[k] + j;
           if(x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == '1') 
           {
                grid[x][y] = '0';
                dfs(grid,x,y);
           }
        }    
    }
};

岛屿的最大面积

题目链接
在这里插入图片描述

题解

1. 使用标记数组标记已经使用过的格子,每次count设置为0,在dfs中每遇到一个是false并且值是1的格子就标记一下,并且count++,dfs返回之后更新下count,找下最大值

代码

class Solution 
{
public:
    int m,n;
    int ret;// 记录最大岛屿面积
    int count;
    bool vis[51][51];
    int maxAreaOfIsland(vector<vector<int>>& grid) 
    {
        m = grid.size(),n = grid[0].size();
        for(int i = 0;i < m;i++)
        {
            for(int j = 0;j < n;j++)
            {
                if(!vis[i][j] && grid[i][j] == 1)
                {
                    vis[i][j] = true;
                    count = 0;
                    dfs(grid,i,j);
                    ret = max(ret,count);
                }
            }
        }
        return ret;
    }
    
    int dx[4] = {-1,1,0,0};
    int dy[4] = {0,0,-1,1};

    void dfs(vector<vector<int>>& grid,int i,int j)
    {
        vis[i][j] = true;
        count++;
        for(int k = 0;k < 4;k++)
        {
            int x = dx[k] + i,y = dy[k] + j;
            if(x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] && grid[x][y] == 1)
            {
                // path在参数中回溯会自动恢复现场,path会比实际的值小
                dfs(grid,x,y);
            }
        }
    }
};

被围绕的区域

题目链接
在这里插入图片描述

题解

1. 怎么检查四周是被X围绕的呢?
正难则反,正着的情况下,如果想要修改中间的O,需要一个dfs,如果想要四周的O不变,又需要一个dfs,如果想要将四周的O修改为X,又需要回溯去还原
2. 算法思路:
可以先使用dfs把四周的O修改为点,再在函数中将点的修改为O,O的修改为X,这就是正难则反

在这里插入图片描述

代码

class Solution 
{
public:
    int m,n;
    
    void solve(vector<vector<char>>& board) 
    {
        m = board.size(),n = board[0].size();
        // 1.把与边界'O'相连的连通块,修改为'.'
        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++)
        {
            if(board[i][0] == 'O') dfs(board,i,0);
            if(board[i][n-1] == 'O') dfs(board,i,n-1);
        }

        // 2.把所有的'.'还原为'O',把'O'改为'X'
        for(int i = 0;i < m;i++)
        {
            for(int j = 0;j < n;j++)
            {
                if(board[i][j] == '.') board[i][j] = 'O';
                // 这里不可以写成if,因为可能是上面的'.'修改成的'O'
                else if(board[i][j] == 'O') board[i][j] = 'X';
            }
        }
    }

    int dx[4] = {-1,1,0,0};
    int dy[4] = {0,0,-1,1};

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

太平洋大西洋水流问题

题目链接
在这里插入图片描述

题解

1. 正着来的话,每个格子可能会走多次,会超时,比如2可以向左走到太平洋中,5也可以向左走到太平洋中
2. 正难则反,可以从小的格子向大的格子走,如果比此格子小则停止,这样不会重复走,从太平洋那边走的使用一个标记数组,从大西洋那边走的,使用一个标记数组,如果两个标记数组都为真则这些格子是可以流向两个洋的

在这里插入图片描述

代码

class Solution 
{
public:
    int m,n;
    vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) 
    {
        vector<vector<int>> ret;
        m = heights.size(),n = heights[0].size();
        vector<vector<bool>> pac(m,vector<bool>(n));
        vector<vector<bool>> atl(m,vector<bool>(n));
        for(int j = 0;j < n;j++)
        {
            dfs(heights,0,j,pac);
            dfs(heights,m-1,j,atl); 
        }

        for(int i = 0;i < m;i++)
        {
            dfs(heights,i,0,pac);
            dfs(heights,i,n-1,atl);
        }

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

    int dx[4] = {-1,1,0,0};
    int dy[4] = {0,0,-1,1};
   
    // oce一定要传引用为了修改原始数组中的值
    void dfs(vector<vector<int>>& heights,int i,int j,vector<vector<bool>>& oce)
    {
        oce[i][j] = true;
        for(int k = 0;k < 4;k++)
        {
            int x = dx[k] + i,y = dy[k] + j;
            if(x >= 0 && x < m && y >= 0 && y < n && heights[i][j] <= heights[x][y] && !oce[x][y])
            {
                dfs(heights,x,y,oce);
            }
        }
    }
};

扫雷游戏

题目链接
在这里插入图片描述

题解

1. 模拟 + dfs
2. 有一个非常重要的点是click下的点如果不是地雷的话,那么后面就不会再翻出地雷了
3. 算法思路:检测开始点击的点是否是地雷,如果是就把该点修改为’X’,如果不是就往下搜索,并且在dfs中新建一个变量统计地雷的个数,如果在该点的八个方向上有地雷,就在该点显示地雷的个数,并且返回(不会把地雷打开),如果没有地雷,把该点修改为’B’,并且在该点的八个方向上去dfs(递归式地展开,可能没有地雷就连续地展开)

在这里插入图片描述

代码

class Solution 
{
public:
    int m,n;
    int dx[8] = {-1,1,0,0,1,1,-1,-1};
    int dy[8] = {0,0,-1,1,1,-1,1,-1};
    vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) 
    { 
      m = board.size(),n = board[0].size();
      int x = click[0],y = click[1];
      // 点击的位置就是一个地雷
      if(board[x][y] == 'M')
      {
        board[x][y] = 'X';
        return board;
      }  
      dfs(board,x,y);
      return board;
    }

    void dfs(vector<vector<char>>& board,int i,int j)
    {
        // 统计一下地雷的个数
        int count = 0;
        // 寻找这一个点的这一圈的地雷个数
        for(int k = 0;k < 8;k++)
        {
            int x = dx[k] + i,y = dy[k] + j;
            if(x >= 0 && x < m && y >= 0 && y < n && board[x][y] == 'M')
            {
                count++;
            }
        }
        
        // 如果周围存在地雷就标记一下
        if(count)
        {
            board[i][j] = count + '0';
            return;
        }
        else
        {
            // 如果周围不存在地雷
            board[i][j] = 'B';
            for(int k = 0;k < 8;k++)
            {
                int x = dx[k] + i,y = dy[k] + j;
                if(x >= 0 && x < m && y >= 0 && y < n && board[x][y] == 'E')
                {
                    dfs(board,x,y);
                }
            }
        }
    }
};

衣橱整理

题目链接
在这里插入图片描述

题解

1. 细节处理:表示x的各数位之和,就是x的各个位置上的数字之和,开始的时候没有注意到
2. 这题就是向右或者向下去dfs,找到 两个坐标的数位之和 <= cnt的点,算出这些点的个数

代码

class Solution 
{
public:
    int m,n;
    int count;
    bool vis[101][101];
    int wardrobeFinishing(int _m, int _n, int cnt) 
    {
        m = _m,n = _n;
        dfs(0,0,cnt);
        if(0 <= cnt) count++;
        return count;
    }
     
    int dx[2] = {1,0};
    int dy[2] = {0,1};

    void dfs(int i,int j,int cnt)
    {
        for(int k = 0;k < 2;k++)
        {
            int x = dx[k] + i,y = dy[k] + j;
            int val1 = x,sum1 = 0;
            int val2 = y,sum2 = 0;
            while(val1)
            {
                sum1 += (val1 % 10);
                val1 /= 10;
            }
            while(val2)
            {
                sum2 += (val2 % 10);
                val2 /= 10;
            }
            if(x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] && sum1 + sum2 <= cnt)
            {
                count++;
                vis[x][y] = true;
                dfs(x,y,cnt);
            }
        }
    }
};

总结

1. 学习到了正难则反的思想
2. 寻找性质相同的联通块,通过dfs将其修改或是统计联通块的个数
3. 无非都是通过4个方向或者是八个方向或者是2个方向上去搜索

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

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

相关文章

LangChain4j(1):初识LangChain4j

1 什么是LangChain和LangChain4j LangChain是一个大模型的开发框架&#xff0c;使用LangChain框架&#xff0c;程序员可以更好的利用大模型的能力&#xff0c;大大提高编程效率。如果你是一个lava程序员&#xff0c;那么对LangChain最简单直观的理解就是&#xff0c;LangChain…

Photoshop 2025安装包下载及Photoshop 2025详细图文安装教程

文章目录 前言一、Photoshop 2025安装包下载二、Photoshop 2025安装教程1.解压安装包2.运行程序3.修改安装路径4.设安装目录5.开始安装6.等安装完成7.关闭安装向导8.启动软件9.安装完成 前言 无论你是专业设计师&#xff0c;还是初涉图像处理的小白&#xff0c;Photoshop 2025…

SQL Server安装程序无法启动:系统兼容性检查失败

问题现象&#xff1a; 运行 SQL Server 2022 安装程序时&#xff0c;提示 “硬件或软件不满足最低要求”&#xff0c;安装向导直接退出或无法继续。 快速诊断 操作系统版本检查&#xff1a; # 查看 Windows 版本&#xff08;需 20H2 或更高&#xff09; winver 支持的系统&…

期权合约作废的话,权利金和保证金会退还么?

在期权交易中&#xff0c;权利金是否可以退回&#xff0c;主要取决于期权的交易情况和合约条款。 期权作废的三种情形 一般来说期权作废一共有三种情况&#xff0c;分别是到期没有行权、主动放弃或者是标的退市了。 第一种是到期未行权&#xff0c;一般来说值得都是虚值期权&…

MIPI计算ECC和CRC工具介绍

一、MIPI简介 MIPI联盟&#xff0c;即移动产业处理器接口&#xff08;Mobile Industry Processor Interface 简称MIPI&#xff09;联盟。MIPI&#xff08;移动产业处理器接口&#xff09;是MIPI联盟发起的为移动应用处理器制定的开放标准和一个规范。MIPI官网https://mipi.org/…

医院管理系统(源码)分享

「医院管理系统&#xff08;源码&#xff09; 源码&#xff1a; https://pan.quark.cn/s/b6e21488fce3 第1章 绪论 1.1 项目背景 随着计算机科学的迅猛发展和互联网技术的不断推进&#xff0c;人们的生活方式发生了巨大的变化&#xff0c;同时也推动了整个软件产业的发展。把…

使用Geotools从DEM数据中读取指定位置的高程实战

目录 前言 一、GridCoverage2D对象介绍 1、GridCoverage2D的属性 2、GridCoverage2D核心方法 3、GridCoverage2D中的高级操作 二、指定位置的高程获取 1、存储原理 2、相关属性的获取 3、获取高程的方法 三、总结 前言 在地理信息科学领域&#xff0c;高程数据是至关重…

STM32F103_LL库+寄存器学习笔记05 - GPIO输入模式,捕获上升沿进入中断回调

导言 GPIO设置输入模式后&#xff0c;一般会用轮询的方式去查看GPIO的电平状态。比如&#xff0c;最常用的案例是用于检测按钮的当前状态&#xff08;是按下还是没按下&#xff09;。中断的使用一般用于计算脉冲的频率与计算脉冲的数量。 项目地址&#xff1a;https://github.…

直播预告 | TDgpt 智能体发布 时序数据库 TDengine 3.3.6 发布会即将开启

从海量监控数据&#xff0c;到工业、能源、交通等场景中实时更新的各类传感器数据&#xff0c;时序数据正在以指数级速度增长。而面对如此庞杂的数据&#xff0c;如何快速分析、自动发现问题、精准预测未来&#xff0c;成为企业数字化转型过程中的关键挑战。 TDengine 的答案是…

vscode 通过Remote-ssh远程连接服务器报错 could not establish connection to ubuntu

vscode 通过Remote-ssh插件远程连接服务器报错 could not establish connection to ubuntu&#xff0c;并且出现下面的错误打印&#xff1a; [21:00:57.307] Log Level: 2 [21:00:57.350] SSH Resolver called for "ssh-remoteubuntu", attempt 1 [21:00:57.359] r…

【JavaScript 简明入门教程】为了Screeps服务的纯JS入门教程

0 前言 0-1 Screeps: World 众所不周知&#xff0c;​Screeps: World是一款面向编程爱好者的开源大型多人在线即时战略&#xff08;MMORTS&#xff09;沙盒游戏&#xff0c;其核心机制是通过编写JavaScript代码来控制游戏中的单位&#xff08;称为“Creep”&#xff09;&#…

Prometheus stack命令行接入springboot服务metrics

使用Prometheus Stack监控SpringBoot应用 本文将详细介绍如何使用Prometheus Stack监控SpringBoot应用的metrics。假设你已经安装了Kubernetes集群&#xff0c;并使用Helm安装了Prometheus Stack全家桶。SpringBoot应用已经配置好&#xff0c;暴露了相应的metrics端点。 Sprin…

Git Bash 设置Notepad++作为默认编辑器

网上搜的时候发现别人搞得有点复杂 &#xff08;绝对正确的方法&#xff09;Git Bash 设置Notepad作为默认编辑器_git 通过notpad 编辑器-CSDN博客 最简单的方式就是重新安装git&#xff0c;然后在选择编辑器的时候&#xff0c;勾选notepad即可

Qt 制作验证码

Qt 制作验证码 #include <QRandomGenerator> #include <QPainterPath> #include <QPainter>// 生成随机数 int r(int a,int b0){return b ? QRandomGenerator::global()->bounded(a, b): QRandomGenerator::global()->bounded(a); }// 生成随机多边形…

【数据结构】二叉树 — 经典OJ面试题剖析!!!

目录 二叉树相关oj题 1. 检查两颗树是否相同 2. 另一棵树的子树 3. 翻转二叉树 4. 判断一颗二叉树是否是平衡二叉树 5. 对称二叉树 6. 二叉树的构建及遍历 7. 二叉树的层序遍历 8. 判断一棵树是不是完全二叉树 9. 二叉树的最近公共祖先 10. 根据前序与中序遍历序列构…

【MySQL】用户账户、角色、口令、PAM

目录 查看用户账户设置 连接 1.本地连接 2.远程连接 账户 角色 操作用户账户和角色 配置口令和账户有效期限 手工使口令过期 配置口令有效期限 PAM身份验证插件 客户端连接&#xff1a;使用 PAM 账户登录 在连接到MySQL服务器并执行查询时&#xff0c;会验证你的身…

SpringBoot 3+ Lombok日志框架从logback改为Log4j2

r要将Spring Boot 3项目中的日志框架从Logback切换到Log4j2&#xff0c;并配置按日期滚动文件和控制台输出&#xff0c;请按照以下步骤操作&#xff1a; 步骤 1&#xff1a;排除Logback并添加Log4j2依赖 在pom.xml中修改依赖&#xff1a; <dependencies><!-- 排除默…

【Tauri2】002——Cargo.toml和入口文件

目录 前言 正文 toml文件的基础 注释——# Comment 键值对——Key/Value 表——[table] 内联表——Inline Table 数组——Array package和crate Cargo.toml文件 Cargo.toml——dependencies Cargo.toml——lib crate-type main.rs 前言 【Tauri2】001——安装及…

二叉树相关算法实现:判断子树与单值二叉树

目录 一、判断一棵树是否为另一棵树的子树 &#xff08;一&#xff09;核心思路 &#xff08;二&#xff09;代码实现 &#xff08;三&#xff09;注意要点 二、判断一棵树是否为单值二叉树 &#xff08;一&#xff09;核心思路 &#xff08;二&#xff09;代码实现…

CSS 美化页面(一)

一、CSS概念 CSS&#xff08;Cascading Style Sheets&#xff0c;层叠样式表&#xff09;是一种用于描述 HTML 或 XML&#xff08;如 SVG、XHTML&#xff09;文档 样式 的样式表语言。它控制网页的 外观和布局&#xff0c;包括字体、颜色、间距、背景、动画等视觉效果。 二、CS…