Day66|图part5:130. 被围绕的区域、827.最大人工岛

news2024/11/28 20:51:48

130. 被围绕的区域

leetcode链接:题目链接

image

这题看起来很复杂,其实跟之前找飞地和找边缘地区的是差不多的,主要分三步:

  • 使用dfs将边缘的岛都找出来,然后用A代替防止混淆;
  • 再用dfs找中间不与任何岛相连的飞地;
  • 最后把之前的A替换成O。

最终代码:

class Solution {
public:
    void dfs(vector<vector<char>> &board, int i, int j, char ch){//找到o把其周围转化为ch
        vector<int> dir = {0,-1,0,1,1,0,-1,0};
        if(i < 0 || j < 0 || i >= board.size() || j >= board[0].size()){
            return;
        }
        if(board[i][j] == 'X' || board[i][j] == 'a'){
            return;
        }
        board[i][j] = ch;
        for(int idx = 0; idx < 4; idx++){
            dfs(board, i + dir[2 * idx], j + dir[2 * idx + 1],ch);
        }

    }
    void solve(vector<vector<char>>& board) {
        int m = board.size();
        int n = board[0].size();

        for(int i = 0; i < m; i++){
            if(board[i][n - 1] == 'O'){
                dfs(board,i, n - 1, 'a');
            }
            if(board[i][0] == 'O'){
                dfs(board,i,0, 'a');
            }
        }
        for(int j = 0; j < n; j++){
            if(board[0][j] == 'O'){
                dfs(board,0, j,'a');
            }
            if(board[m - 1][j] == 'O'){
                dfs(board, m - 1, j,'a');
            }

        }
        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] =='a'){
                    board[i][j] = 'O';
                }

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

这里有几点注意的:

  • dfs函数中,除了等于X需要return,等于A也需要return,否则递归就没办法结束。
  • 只需要dfs淹没周围一圈的岛,中间的岛不用再dfs找了,直接替换就行,因为本题没有让我们以整个岛为单位做一些事情。

417. 太平洋大西洋水流问题

leetcode链接:题目链接

image

image

输入: heights = [[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]]
输出: [[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]
示例 2:

输入: heights = [[2,1],[1,2]]
输出: [[0,0],[0,1],[1,0],[1,1]]

首先这题题目我都没怎么看懂,理解一下题意。

输入是一个二维数组,只要位于该点的值比四个方向的高就可以流向其他方向,最终既可以流向右边、下边(大西洋),又可以流向左边、上边(太平洋)的符合结果,输出result。

首先能想到一个很朴素的思路就是,对每个点都判断一下是否能同时流向大西洋和太平洋。这种思路的实现代码如下:

class Solution {
private:
    int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1};
    void dfs(vector<vector<int>>& heights, vector<vector<bool>>& visited, int x, int y) {
        if (visited[x][y]) return;

        visited[x][y] = true;

        for (int i = 0; i < 4; i++) {
            int nextx = x + dir[i][0];
            int nexty = y + dir[i][1];
            if (nextx < 0 || nextx >= heights.size() || nexty < 0 || nexty >= heights[0].size()) continue;
            if (heights[x][y] < heights[nextx][nexty]) continue; // 高度不合适

            dfs (heights, visited, nextx, nexty);
        }
        return;
    }
  bool isResult(vector<vector<int>>& heights, int x, int y) {
        vector<vector<bool>> visited = vector<vector<bool>>(heights.size(), vector<bool>(heights[0].size(), false));

        // 深搜,将x,y出发 能到的节点都标记上。 
        dfs(heights, visited, x, y);
        bool isPacific = false;
        bool isAtlantic = false;

        // 以下就是判断x,y出发,是否到达太平洋和大西洋 
        for (int j = 0; j < heights[0].size(); j++) {
            if (visited[0][j]) {
                isPacific = true;
                break;
            }
        }
        for (int i = 0; i < heights.size(); i++) {
            if (visited[i][0]) {
                isPacific = true;
                break;
            }
        }
        for (int j = 0; j < heights[0].size(); j++) {
            if (visited[heights.size() - 1][j]) {
                isAtlantic = true;
                break;
            }
        }
        for (int i = 0; i < heights.size(); i++) {
            if (visited[i][heights[0].size() - 1]) {
                isAtlantic = true;
                break;
            }
        }
        if (isAtlantic && isPacific) return true;
        return false;
    }
public:

    vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
        vector<vector<int>> result;
        // 遍历每一个点,看是否能同时到达太平洋和大西洋 
        for (int i = 0; i < heights.size(); i++) {
            for (int j = 0; j < heights[0].size(); j++) {
                if (isResult(heights, i, j)) result.push_back({i, j});
            }
        }
        return result;
    }
};

这种思路很直白,但很明显,以上代码超时了。 来看看时间复杂度。

遍历每一个节点,是 m * n,遍历每一个节点的时候,都要做深搜,深搜的时间复杂度是: m * n

那么整体时间复杂度 就是 O(m^2 * n^2) ,这是一个四次方的时间复杂度。

优化

那么我们可以 反过来想,从太平洋边上的节点 逆流而上,将遍历过的节点都标记上。 从大西洋的边上节点 逆流而长,将遍历过的节点也标记上。 然后两方都标记过的节点就是既可以流太平洋也可以流大西洋的节点。

class Solution {
private:
    int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1}; // 保存四个方向

    // 从低向高遍历,注意这里visited是引用,即可以改变传入的pacific和atlantic的值
    void dfs(vector<vector<int>>& heights, vector<vector<bool>>& visited, int x, int y) {
        if (visited[x][y]) return;
        visited[x][y] = true;
        for (int i = 0; i < 4; i++) { // 向四个方向遍历
            int nextx = x + dir[i][0];
            int nexty = y + dir[i][1];
            // 超过边界
            if (nextx < 0 || nextx >= heights.size() || nexty < 0 || nexty >= heights[0].size()) continue;
            // 高度不合适,注意这里是从低向高判断
            if (heights[x][y] > heights[nextx][nexty]) continue;

            dfs (heights, visited, nextx, nexty);
        }
        return;

    }

public:
vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
        vector<vector<int>> result;
        int n = heights.size();
        int m = heights[0].size(); // 这里不用担心空指针,题目要求说了长宽都大于1

        // 记录从太平洋边出发,可以遍历的节点
        vector<vector<bool>> pacific = vector<vector<bool>>(n, vector<bool>(m, false));

        // 记录从大西洋出发,可以遍历的节点
        vector<vector<bool>> atlantic = vector<vector<bool>>(n, vector<bool>(m, false));

        // 从最上最下行的节点出发,向高处遍历
        for (int i = 0; i < n; i++) {
            dfs (heights, pacific, i, 0); // 遍历最上行,接触太平洋
            dfs (heights, atlantic, i, m - 1); // 遍历最下行,接触大西洋
        }

        // 从最左最右列的节点出发,向高处遍历
        for (int j = 0; j < m; j++) {
            dfs (heights, pacific, 0, j); // 遍历最左列,接触太平洋
            dfs (heights, atlantic, n - 1, j); // 遍历最右列,接触大西洋
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                // 如果这个节点,从太平洋和大西洋出发都遍历过,就是结果
                if (pacific[i][j] && atlantic[i][j]) result.push_back({i, j});
            }
        }
        return result;
    }
};

所以 调用dfs函数,只要参数传入的是 数组pacific,那么地图中 每一个节点其实就遍历一次,无论你调用多少次

同理,调用 dfs函数,只要 参数传入的是 数组atlantic,地图中每个节点也只会遍历一次。

所以,以下这段代码的时间复杂度是 2 * n * m。 地图用每个节点就遍历了两次,参数传入pacific的时候遍历一次,参数传入atlantic的时候遍历一次。

827. 最大人工岛

leetcode链接:力扣链接

给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。

返回执行此操作后,grid 中最大的岛屿面积是多少?

岛屿 由一组上、下、左、右四个方向相连的 1 形成。

示例 1:

输入: grid = [[1, 0], [0, 1]]
输出: 3
解释: 将一格0变成1,最终连通两个小岛得到面积为 3 的岛屿。
示例 2:

输入: grid = [[1, 1], [1, 0]]
输出: 4
解释: 将一格0变成1,岛屿的面积扩大为 4。
示例 3:

输入: grid = [[1, 1], [1, 1]]
输出: 4
解释: 没有0可以让我们变成1,面积依然为 4

https://www.programmercarl.com/0827.%E6%9C%80%E5%A4%A7%E4%BA%BA%E5%B7%A5%E5%B2%9B.html#%E4%BC%98%E5%8C%96%E6%80%9D%E8%B7%AF

先放这里放一下。题目居然是hard,不太想做岛屿类的题了,换换脑子。

总结

  • 岛屿问题的dfs/bfs的代码基本大差不差,主要还是主函数中处理逻辑的问题;
  • 学习带有 visited的dfs的写法。

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

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

相关文章

天软特色因子看板 (2023.09 第07期)

该因子看板跟踪天软特色因子A02002 (近一月尾盘成交占比(%))&#xff0c;该因子为近一个月尾盘成交量占比均值因子&#xff0c;用以刻画股票在收盘时&#xff0c;主力资金的流动影响。近一月尾盘成交占比(%)越小&#xff0c;表示多方或空方无力量。近一月尾盘成交占比(%)越大&a…

Qt5开发及实例V2.0-第一章Qt概述及Qt5的安装

Qt5开发及实例V2.0-第一章-Qt概述及Qt5的安装 第一章-Qt概述1.1 什么是Qt1.2 Qt 5的安装1.2.1 下载安装Qt 51.2.2 运行Qt 5 Creator1.2.3 Qt 5开发环境 1.3 Qt 5开发步骤及实例1.3.1 设计器Qt 5 Designer实现1.3.2 代码实现简单实例 L1.2 Qt 5安装&#xff1a;概念解析L1.3 Qt …

JS Set和Map数据结构

Set和Map数据结构 1. Set数据结构1.1 Set 增删改查1.1.1 add() 方法1.1.2 delete()1.1.3 has()1.1.4 clear()1.1.5 size 1.2 Set 遍历方法1.2.1 keys()1.2.2 values()1.2.3 entries()1.2.3 forEach() 2. Map数据类型2.1 Map 增删改查2.1.1 set()2.1.2 get()2.1.3 has()2.1.4 de…

【C++从0到王者】第三十一站:map与set

文章目录 一、关联式容器二、pair键值对三、set1. set的介绍2. set的部分接口以及应用3. count4. lower_bound和upper_bound5. equal_range6. multiset容器 四、map1. map的介绍2. map的一些常见接口以及使用3. map的[]运算符重载4. 使用map改进一些题5. multimap容器 五、map和…

Laravel框架 - IOC容器详解

IOC 容器代码 好了&#xff0c;说了这么多&#xff0c;下面要上一段容器的代码了. 下面这段代码不是laravel 的源码&#xff0c; 而是来自一本书《laravel 框架关键技术解析》. 这段代码很好的还原了laravel 的服务容器的核心思想. 代码有点长&#xff0c; 小伙伴们要耐心看. …

分享VR眼镜加密播放器OEM方案

随着科技的发展&#xff0c;电子成品更新换代很快&#xff0c;用户的娱乐工具也更加多样化&#xff0c;从电脑、手机、平板在到现在使用越来越多的VR眼镜&#xff0c;给用户的体验也越来越多样。而对于内容提供商来说&#xff0c;内容是其竞争优势所在。那么如何做好视频在VR眼…

【Unity】【C#】【VS】如何将VS写的通用C#窗体程序修改为Unity程序

【背景】 需要将一个Visual2019写的C#用Unity改写。 Unity写窗体程序的一大优点就是美观了,看看这默认界面。 但是缺点就是启动时有个Unity过场动画。 【问题】 Unity虽然用的也是C#,但是和Visual2019的通用窗体C#采用的界面显示的库,图像处理,组成一个脚本的基本函数等…

Linux 作业

一. 题目 二.作业内容 第一题&#xff1a; 因老师要求上传安装后远程连接XShell截图&#xff0c;如下&#xff1a; 制作yum缓存&#xff1a;[rootRHEL8 ~]# yum makecache 安装gcc&#xff1a;[rootRHEL8 ~]# yum install gcc -y 制作快照&#xff1a;快照&#xff0c;初始 s…

《rust学习一》 fleet 配置rust环境

最近被网上的rust教徒洗脑了&#xff0c;尝试一下学习rust语言&#xff0c;首先搭建开发环境 准备工作&#xff1a; 安装rust&#xff0c;fleet 第一步&#xff1a;在fleet内打开空文件夹 第二步&#xff1a;创建项目文件 cargo new HelloWorld第三步&#xff1a;Rust&#x…

RFID技术在仓储物流供应链管理中的应用

仓储物流供应链管理的透明度和库存周转率成为管控的重点&#xff0c;为了提高仓储物流的效率和减少库存损失&#xff0c;RFID技术被广泛应用于仓储、分发、零售管理等各个环节&#xff0c;为供应链管理带来了巨大的改变和提升。 首先&#xff0c;采用RFID技术进行仓库物流智能化…

基于SpringBoot+Vue实现的党校培训管理系统源代码+数据库

一、简介 项目简介&#xff1a; 基于微服务架构的党校培训管理系统&#xff0c; 完整代码下载地址&#xff1a;党校培训管理系统 大体总结&#xff1a; 前端使用Vue.js框架&#xff0c;UI组件库使用Element UI与Ant Design Vue&#xff0c;后端基于Spring Boot&#xff0c;使…

verilog学习笔记(1)module实例化2

移位寄存器多路选择器 我的代码&#xff1a; module top_module ( input clk, input [7:0] d, input [1:0] sel, output [7:0] q );wire [7:0] w1;wire [7:0] w2;wire [7:0] w3;my_dff8 my_dff8_1(.clk(clk),.d(d),.q(w1));my_dff8 my_dff8_2(.clk(clk),.d(w1),.q(w2));my_d…

Learn Prompt-提供示例

目前我们与 ChatGPT 交流的主要形式是文字。提示除了指令问题的形式外&#xff0c;还可以包含例子。特别是当我们需要具体的输出时&#xff0c;提供例子可以省去我们对具体任务的解释&#xff0c;帮助ChatGPT更好地理解我们的确切需求&#xff0c;从而提供更准确&#xff0c;更…

如何使用高压放大器驱动高容性负载

使用高压放大器驱动高容性负载是一个具有挑战性的任务&#xff0c;需要仔细考虑电路设计和操作技巧。下面西安安泰Aigtek将为您介绍一些关于如何使用高压放大器驱动高容性负载的方法和注意事项。 首先&#xff0c;让我们了解一下高容性负载。高容性负载通常指电容值较大的负载元…

邮件数据安全案例 | 有一种遇见,叫相见恨晚

Mr.赵回忆和联通相遇的时刻&#xff0c;他说&#xff0c;用一句诗来形容恰如其分&#xff0c;“众里寻他千百度&#xff0c;蓦然回首&#xff0c;那人却在&#xff0c;灯火阑珊处” 。 中国联合网络通信集团有限公司在国内31个省&#xff08;自治区、直辖市&#xff09;和境外…

前后端分离毕设项目之产业园区智慧公寓管理系统设计与实现(内含源码+文档+教程)

博主介绍&#xff1a;✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久&#xff0c;选择我们就是选择放心、选择安心毕业✌ &#x1f345;由于篇幅限制&#xff0c;想要获取完整文章或者源码&#xff0c;或者代做&am…

Codeforces Round 896 (Div. 1) C. Travel Plan(树形dp+组合数学)

题目 有一棵n(1<n<1e18)个点的树&#xff0c; 点i连着2*i和2*i1两个点&#xff0c;构成一棵完全二叉树 对于每个点i&#xff0c;记其值为a[i]&#xff0c;a[i]可以取[1,m](1<m<1e5)的整数 记i到j的简单路径上的最大值为s[i][j]&#xff0c; 则一棵权值确定的树…

mysql中update更新时加条件和不加条件速度对比

测试时有时需要执行更新操作&#xff0c;想知道大量数据update时加where条件和不加where条件速度差异如何&#xff0c;正好有条件测试&#xff0c;记录一下。 数据&#xff1a;9张表&#xff0c;每张表300w条数据 一、对9张表进行单字段更新时不加条件(如&#xff1a;update …

支付功能、支付平台、支持渠道如何测试?

有学员提问&#xff1a;作为一个支付平台&#xff0c;接入了快钱、易宝或直连银行等多家的渠道&#xff0c;内在的产品流程是自己的。业内有什么比较好的测试办法&#xff0c;来测试各渠道及其支持的银行通道呢&#xff1f; 作为产品&#xff0c;我自己办了十几张银行卡方便测…

web大作业 比赛报名页面+ 团队介绍页面 制作

web大作业 比赛报名页面 团队介绍页面 制作【附源代码】 文章目录 web大作业 比赛报名页面 团队介绍页面 制作【附源代码】前言报名界面效果图如下&#xff1a;代码实现计时器效果实现&#xff08;jqueryboostrap&#xff09; 团队介绍页面模拟框代码&#xff1a;CSS代码 前言 …