《剑指 Offer》专项突破版 - 面试题 105 和 106 : 最大的岛屿和二分图(C++ 实现)

目录

面试题 105 : 最大的岛屿

面试题 106 : 二分图


 


面试题 105 : 最大的岛屿

题目

海洋岛屿地图可以用由 0、1 组成的二维数组表示,水平或竖直方向相连的一组 1 表示一个岛屿,请计算最大的岛屿的面积(即岛屿中 1 的数目)。例如,在下图中有 4 个岛屿,其中最大的岛屿的面积为 5。

分析

应用与图相关的算法解决问题的第 1 步是找出问题中隐含的图。看到这个题目之后,可能会有人问:输入的是一个矩阵,图在哪里?其实图是节点(即顶点)和边的集合,因此需要找出图的节点和边。这个题目关注的是地图中的岛屿,也就是矩阵中的 1。矩阵中的每个值为 1 的格子都是图中的一个节点。矩阵中的一个格子可能与位于它上、下、左、右的 4 个格子相邻,两个相邻的值为 1 的格子之间有一条边相连。例如,可以用下图表示上图中的岛屿。

即一个非连通图中有 4 个连通分量,通过计算每个连通分量中节点的数目,就能知道最大的岛屿的面积为 5

int maxAreaOfIsland(vector<vector<int>>& grid) {
    int rows = grid.size(), cols = grid[0].size();
    vector<vector<bool>> isVisited(rows, vector<bool>(cols, false));
​
    int maxArea = 0;
    for (int i = 0; i < rows; ++i)
    {
        for (int j = 0; j < cols; ++j)
        {
            if (grid[i][j] == 1 && !isVisited[i][j])
            {
                int area = getArea(grid, isVisited, i, j);
                maxArea = max(maxArea, area);
            }
        }
    }
    return maxArea;
}

广度优先搜索

int getArea(vector<vector<int>>& grid, vector<vector<bool>>& isVisited, int i, int j) {
    queue<vector<int>> q;
    q.push(vector<int>{ i, j });
    isVisited[i][j] = true;
​
    vector<vector<int>> dirs = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
    int area = 0;
    while (!q.empty())
    {
        vector<int> front = q.front();
        q.pop();
        ++area;
​
        for (vector<int>& dir : dirs)
        {
            int r = front[0] + dir[0];
            int c = front[1] + dir[1];
            if (r >= 0 && r < grid.size() &&
                c >= 0 && c < grid[0].size() &&
                grid[r][c] == 1 && !isVisited[r][c])
            {
                q.push(vector<int>{ r, c });
                isVisited[r][c] = true;
            }
        }
    }
    return area;
}

上述代码中队列的元素为矩阵中的坐标,每个坐标都包含行号和列号这两个值,用一个长度为 2 的数组表示

二维数组 dirs 表示在矩阵中向上、下、左、右这 4 个方向前进一步时坐标的变化。在矩阵中向上移动一步时行号减 1 而列号不变,所以坐标的改变值为 (-1, 0),其他方向的改变值类似。用当前坐标加上坐标的改变值就得到向不同方向前进一步之后的坐标。这样写代码的好处是容易用一个简洁的循环实现向 4 个不同方向前进

深度优先搜索

int getArea(vector<vector<int>>& grid, vector<vector<bool>>& isVisited, int i, int j) {
    isVisited[i][j] = true;
    int area = 1;
​
    vector<vector<int>> dirs = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 }};
    for (vector<int>& dir : dirs)
    {
        int r = i + dir[0];
        int c = j + dir[1];
        if (r >= 0 && r < grid.size() && 
            c >= 0 && c < grid[0].size() &&
            grid[r][c] == 1 && !isVisited[r][c])
        {
            area += getArea(grid, isVisited, r, c);
        }
    }
    return area;
}


面试题 106 : 二分图

题目

如果能将一个图中的节点分成 A、B 两部分,使任意一条边的一个节点属于 A 而另一个节点属于 B,那么该图就是一个二分图。输入一个由数组 graph 表示的图,graph[i] 中包含所有和节点 i 相邻的节点,请判断该图是否为二分图。

例如,如果输入 graph 为 [[1, 3], [0, 2], [1, 3], [0, 2]],那么可以将节点分为 { 0, 2 }、{ 1, 3 } 两个部分,因此该图是一个二分图,如下图 (a) 所示。如果输入 graph 为 [[1, 2, 3], [0, 2], [0, 1, 3], [0, 2]],那么该图是一个非二分图,如下图 (b) 所示。

分析

根据题目提供的信息,二分图的节点可以分成两种不同的类型,任意一条边的两个节点分别属于两种不同的类型。可以为图中的所有节点着色,两种不同类型的节点分别涂上不同的颜色。如果任意一条边的两个节点都能被涂上不同的颜色,那么整个图就是一个二分图

一个图可能包含多个连通分量,需要逐一对每个连通分量着色

bool isBipartite(vector<vector<int>>& graph) {
    int n = graph.size();
    vector<int> colors(n, -1);
    for (int i = 0; i < n; ++i)
    {
        if (colors[i] == -1)
        {
            if (!setColor(graph, colors, i, 0))
                return false;
        }
    }
    return true;
}

图中有 n 个节点,于是创建一个长度为 n 的数组 colors 记录每个节点的颜色,节点 i 的颜色保存在 colors[i] 中

  1. 如果节点 i 还没有被着色,那么 colors[i] 的值为 -1

  2. 如果节点 i 已经被着色,那么 colors[i] 的值为 0 或 1

函数 setColor 用来对以节点 i 为起始节点的一个连通分量着色,它的返回值用来表示能否按照二分图的规则对连通分量的所有节点进行着色。为了能够给所有节点着色,需要搜索所有与节点 i 连通的节点,每搜索到一个尚未着色的节点就按照二分图的规则给它涂上颜色

利用广度优先搜索对连通分量着色

bool setColor(vector<vector<int>>& graph, vector<int>& colors, int i, int color) {
    queue<int> q;
    q.push(i);
    colors[i] = color;
    while (!q.empty())
    {
        int pos = q.front();
        q.pop();
        for (int adjPos : graph[pos])
        {
            if (colors[adjPos] == -1)
            {
                q.push(adjPos);
                colors[adjPos] = 1 - colors[pos];
            }
            else
            {
                if (colors[adjPos] == colors[pos])
                    return false;
            }
        }
    }
    return true;
}

利用深度优先搜索对连通分量着色

bool setColor(vector<vector<int>>& graph, vector<int>& colors, int i, int color) {
    if (colors[i] >= 0)
        return colors[i] == color;
​
    colors[i] = color;
    for (int adjPos : graph[i])
    {
        if (!setColor(graph, colors, adjPos, 1 - color))
            return false;
    }
    return true;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何使用Jellyfin+cpolar低成本部署私人影音平台并实现无公网IP远程访问

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及&#xff0c;各种各样的使用需求也被开发出来&…

事务的隔离性

参考: 小林coding MySQL服务器同时处理多个事务时&#xff0c;会出现脏读&#xff0c;不可重复读&#xff0c;幻读问题。 脏读 一个事务读到另一个未提交事务修改过的数据。 举例&#xff1a;事务A先读取数据&#xff0c;并对其进行修改&#xff0c;此时事务B进行读取获取到…

【python】实时获取当前屏幕图像

一、代码 import pyautogui import cv2 import numpy as np import time # 获取屏幕尺寸 screen_width, screen_height pyautogui.size() screen_size (1920, 1080) cv2.namedWindow("Screen Capture", cv2.WINDOW_NORMAL) # cv2.resizeWindow("Screen Captu…

大话设计模式——21.中介者模式(Mediator Pattern)

简介 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互 UML图 应用场景 大量的连接使得一个对象不可能在没有其他对象的支持下工作&#xff0c;系统表现为一个不可分割的…

视频压缩软件有哪些?教你免费压缩视频的方法。

视频文件通常占据较大的存储空间&#xff0c;压缩视频可以有效节省存储成本&#xff0c;并使得视频文件更容易在网络上分享和传输。在网络带宽有限的情况下&#xff0c;压缩视频可以减少视频流量&#xff0c;提高视频在低带宽环境下的流畅性和观看体验。哪款视频压缩软件最好用…

海外云手机提供的当地IP有什么好处?

在全球化的数字时代&#xff0c;海外云手机成为许多企业和个人的首选&#xff0c;用于运营海外社媒、远程办公等活动。海外云手机的一个重要特点是可以选择不同国家的IP地址&#xff0c;以实现更灵活的运营策略和网络访问控制。 首先&#xff0c;让我们探讨海外云手机可以选不同…

element vue 日期时间组件封装

一、背景 年、月、周、日的时间范围类型&#xff0c;选择对应的日期类型&#xff0c;会传参给后端一个dateType参数&#xff0c;用于后端判断&#xff0c;进行数据抽稀。 二、实现效果 三、代码 完整代码&#xff1a; //年月周日&#xff0c;组件封装 //vue3 setup <scrip…

10. 学生成绩管理系统

内容概要 认识了解数组 可重复添加数组的命令 认识并了解数组 1.什么是数组 数组用来存储一组同类型的数据 2.数组的使用 创建数组 使用数组&#xff1a;加入成员、获取数组中成员的内容&#xff08;值&#xff09;、删除成员、取数组成员数、清除数组 3.需要注意的问…

通信指挥类装备(多链路聚合设备)

随着信息技术的迅猛发展&#xff0c;通信指挥类装备在应急管理等领域中发挥着越来越重要的作用。多链路聚合设备具有4G/5G、专网、卫星网、宽带自组网、WiFi等多种网络接入和融合能力&#xff0c;同时使用用户≥200&#xff0c;防护等级≥IP66&#xff0c;单电池可连续工作≥4h…

Prometheus接入AlterManager配置邮件告警(基于K8S环境部署)

目录 一.配置Alertmanager告警发送至邮箱二.Prometheus接入AlertManager三.部署PrometheusAlterManager(放到一个Pod中)四. 测试告警 基于 此环境做实验 一.配置Alertmanager告警发送至邮箱 1.创建AlertManager ConfigMap资源清单 vim alertmanager-cm.yaml --- kind: Confi…

C++ 中的默认成员函数详解

在 C 中&#xff0c;有六种默认成员函数会在创建类时由编译器自动生成。但需要注意的是&#xff0c;如果我们手动在类中定义了其中一种成员函数&#xff0c;编译器便不会自动生成该成员函数。 构造函数 作用&#xff1a;构造函数在实例化对象时自动被调用&#xff0c;用于初始化…

Ubuntu 安装Java、Git、maven、Jenkins等持续集成环境

Ubuntu 持续集成 安装OpenJdk 查看所有可安装的 JDK 版本 apt list OpenJDK\*使用 apt 安装 JDK&#xff08;以 11为例&#xff09;,最好是用11&#xff0c;java8对应的jenkins会有兼容问题。 sudo apt install openjdk-11-jdk openjdk-11-jre安装成功后&#xff0c;可以使用以…

IP地址定位技术在各领域的作用

IP地址定位是通过确定IP地址的物理位置来定位一个设备的技术&#xff0c;它在现代社会的多个领域中都有着广泛的应用。以下将详细探讨IP地址定位的应用场景&#xff0c;以期对读者有所启发。 首先&#xff0c;在网络安全领域&#xff0c;IP地址定位发挥着至关重要的作用。网络…

6、Qt-button设置

前言&#xff1a;记录Button使用的一些技巧 一、无边框前端设置 二、无边框后台设置 ui->PushButton->setStyleSheet("border:none;") 四、参考文献 4.1 Qt按钮实现无边框效果的方法之一_qt设置按钮无边框-CSDN博客

Linux 秋招必知必会(一、文件I/O、文件和目录)

一、基本概念 1. shell shell&#xff1a;命令解释器&#xff0c;根据输入的命令执行相应命令 bash&#xff08;Bourne-Again-SHell&#xff09;是一个为 GNU 计划编写的 Unix shellLinux 默认的 shell&#xff1a;/bin/bash 2. 类 Unix 系统目录结构 Ubuntu 没有盘符这个…

XT-50冲击试样缺口夏比投影仪

概述&#xff1a; 冲击试样投影仪是我们根据目前国内广大用户的实际需求和GB/T229—2020《金属夏比缺口冲击试验方法》中对冲击试样缺口的要求而设计、开发的一种专用于检查夏比V型和U型冲击试样缺口加工质量的专用光学仪器&#xff0c;该仪器是利用光学投影方法将被测的冲击试…

天诚智慧校园管理系统,变革高校物联网锁数智化通行新模式

三月草长莺飞&#xff0c;四月柳绿莺啼&#xff0c;在万物复苏的美好时节&#xff0c;历经半年的精心酝酿与匠心打磨&#xff0c;全场景AIoT解决方案服务商——江苏新巢天诚智能技术有限公司&#xff08;以下简称“天诚”&#xff09;正式推出新一代高校数智化通行管理平台——…

Canon佳能打印机在扫描时会提示缺少组件解决方法

问题截图 解决方法 1.复制佳能驱动网址&#xff1a;下载与支持 – 服务与支持 - 佳能&#xff08;中国&#xff09;到浏览器访问&#xff0c;输入打印机型号&#xff0c;点击驱动程序。 2.在驱动程序栏目下&#xff0c;下载并安装打印机驱动。 3.点击应用程序栏目&#xff0c;…

一文了解AI边缘计算盒子是什么产品设备

大家听说过AI边缘计算盒子吗&#xff1f;不知道你有没有注意到&#xff0c;最近这款产品设备在科技圈内可是火得不要不要的&#xff01;那么&#xff0c;它究竟是什么东西呢&#xff1f;别着急&#xff0c;小编我今天就来给大家揭晓。 边缘计算盒子是什么? 边缘计算盒子是一种…

报表控件 Stimulsoft 常见问题:从代码启用缓存

Stimulsoft Ultimate &#xff08;原Stimulsoft Reports.Ultimate&#xff09;是用于创建报表和仪表板的通用工具集。该产品包括用于WinForms、ASP.NET、.NET Core、JavaScript、WPF、PHP、Java和其他环境的完整工具集。无需比较产品功能&#xff0c;Stimulsoft Ultimate包含了…