【算法与数据结构】417、LeetCode太平洋大西洋水流问题

文章目录

  • 一、题目
  • 二、解法
  • 三、完整代码

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。

一、题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、解法

  思路分析:题目要求雨水既能流向太平洋也能流向大西洋的网格。雨水流向取决于网格的高度。一个比较直接的方式是对每个网格做深度优先搜索,去判断该网格点是否连接太平洋和大西洋,连接的条件就是小于或者等于网格的高度。这样的方法对于当个网格点的复杂度是 O ( m × n ) O(m \times n) O(m×n),一共有 O ( m × n ) O(m \times n) O(m×n)个网格,总的复杂度是 O ( m 2 × n 2 ) O(m^2 \times n^2) O(m2×n2)。这种方法的缺点是没有利用点与点之间的关系,单个网格点的遍历不能再下一次遍历中利用。

  为了能充分利用点与点之间的关系,逆向思维一下,顺着雨水流向逆向遍历。从太平洋边上的节点出发,标记所有能流入太平洋的网格点;同样的方法,从大西洋边上的节点出发,标记所有能流入大西洋的的网格点。然后找到同时有太平洋和大西洋标记的节点输出。

  程序如下

// 417、太平洋大西洋水流问题
class Solution {
private:vector<vector<int>> result;vector<vector<int>> delta_x_y = { {0, -1}, {0, 1}, {-1, 0}, {1, 0} };	// 上下左右四个方向的偏移量void dfs(const vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y) {	// 1、递归输入参数visited[x][y] = true;// 3、单层递归逻辑for (int i = 0; i < 4; i++) {int nextx = x + delta_x_y[i][0];int nexty = y + delta_x_y[i][1];//  2、终止条件  逆流而上式的遍历 grid[nextx][nexty] < grid[x][y]if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size() || visited[nextx][nexty]  || grid[nextx][nexty] < grid[x][y]) continue;	dfs(grid, visited, nextx, nexty);}}
public:vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {vector<vector<bool>> pacific = vector<vector<bool>>(heights.size(), vector<bool>(heights[0].size(), false));	// 遍历过的坐标vector<vector<bool>> Atlanti = vector<vector<bool>>(heights.size(), vector<bool>(heights[0].size(), false));for (int i = 0; i < heights[0].size(); i++) {		// 遍历边界行dfs(heights, pacific, 0, i);				// 第一行dfs(heights, Atlanti, heights.size() - 1, i);	// 最后一行						}for (int j = 0; j < heights.size(); j++) {	// 遍历大西洋的网格点dfs(heights, pacific, j, 0);				// 第一列dfs(heights, Atlanti, j, heights[0].size() - 1);	// 最后一列			}for (int i = 0; i < heights.size(); i++) {	// 遍历行 for (int j = 0; j < heights[0].size(); j++) {	// 遍历列if (pacific[i][j] && Atlanti[i][j]) result.push_back({i, j});	// 深度优先搜索,将连接的陆地都标记上true}}return result;}
}; 

复杂度分析:

  • 时间复杂度: O ( m × n ) O(m \times n) O(m×n),其中 m m m n n n分别是网格数组的行数和列数。深度优先搜索的时间复杂度为 O ( m × n ) O(m \times n) O(m×n),主程序当中使用了四个for循环,前两个用来遍历边界,后两个用来遍历太平洋和大西洋的标记数组。前两个for循环的时间复杂度不是 O ( m × ( m × n ) + n × ( m × n ) ) = O ( ( m + n ) × ( m × n ) ) O(m \times (m \times n)+n \times (m \times n)) = O((m+n) \times (m \times n)) O(m×(m×n)+n×(m×n))=O((m+n)×(m×n))。因为我们引入了标记数组,标记过的网格不会多次遍历,实际上的复杂度是两个标记数组遍历的复杂度 O ( 2 × ( m × n ) ) O(2 \times (m \times n)) O(2×(m×n)),后两个循环的复杂度也是 O ( m × n ) O(m \times n) O(m×n)。因此总的时间复杂度为 O ( 3 × m × n ) = O ( m × n ) O(3 \times m \times n) = O(m \times n) O(3×m×n)=O(m×n)
  • 空间复杂度: O ( m × n ) O(m \times n) O(m×n)

三、完整代码

# include <iostream>
# include <vector>
# include <string>
using namespace std;// 417、太平洋大西洋水流问题
class Solution {
private:vector<vector<int>> result;vector<vector<int>> delta_x_y = { {0, -1}, {0, 1}, {-1, 0}, {1, 0} };	// 上下左右四个方向的偏移量void dfs(const vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y) {	// 1、递归输入参数visited[x][y] = true;// 3、单层递归逻辑for (int i = 0; i < 4; i++) {int nextx = x + delta_x_y[i][0];int nexty = y + delta_x_y[i][1];//  2、终止条件  逆流而上式的遍历 grid[nextx][nexty] < grid[x][y]if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size() || visited[nextx][nexty]  || grid[nextx][nexty] < grid[x][y]) continue;	dfs(grid, visited, nextx, nexty);}}
public:vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {vector<vector<bool>> pacific = vector<vector<bool>>(heights.size(), vector<bool>(heights[0].size(), false));	// 遍历过的坐标vector<vector<bool>> Atlanti = vector<vector<bool>>(heights.size(), vector<bool>(heights[0].size(), false));for (int i = 0; i < heights[0].size(); i++) {		// 遍历边界行dfs(heights, pacific, 0, i);				// 第一行dfs(heights, Atlanti, heights.size() - 1, i);	// 最后一行						}for (int j = 0; j < heights.size(); j++) {	// 遍历大西洋的网格点dfs(heights, pacific, j, 0);				// 第一列dfs(heights, Atlanti, j, heights[0].size() - 1);	// 最后一列			}for (int i = 0; i < heights.size(); i++) {	// 遍历行 for (int j = 0; j < heights[0].size(); j++) {	// 遍历列if (pacific[i][j] && Atlanti[i][j]) result.push_back({i, j});	// 深度优先搜索,将连接的陆地都标记上true}}return result;}
}; void my_print(vector<vector<int>> result, string message) {cout << message << endl;for (vector<vector<int>>::iterator it = result.begin(); it != result.end(); it++) {for (vector<int>::iterator jt = (*it).begin(); jt != (*it).end(); jt++) {cout << *jt << " ";}cout << endl;}
}int main() {//vector<vector<int>> 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} };//vector<vector<int>> heights = { {1} };vector<vector<int>> heights = { {3,3,3,3,3,3}, {3,0,3,3,0,3 }, {3,3,3,3,3,3} };Solution s1;vector<vector<int>> result = s1.pacificAtlantic(heights);my_print(result, "结果:");system("pause");return 0;
}

end

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

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

相关文章

element ui 安装 简易过程 已解决

我之所以将Element归类为Vue.js&#xff0c;其主要原因是Element是&#xff08;饿了么团队&#xff09;基于MVVM框架Vue开源出来的一套前端ui组件。我最爱的就是它的布局容器&#xff01;&#xff01;&#xff01; 下面进入正题&#xff1a; 1、Element的安装 首先你需要创建…

Java设计模式-结构型-适配器模式

Java设计模式-结构型-适配器模式 本文我们简单说下设计模式中的适配器模式。 一、概述 ​ 与电源适配器相似&#xff0c;在适配器模式中引入了一个被称为适配器(Adapter)的包装类&#xff0c;而它所包装的对象称为适配者(Adaptee)&#xff0c;即被适配的类。适配器的实现就是…

【DDD】学习笔记-深入理解简单设计

测试驱动开发遵守了测试—开发—重构的闭环。测试设定了新功能的需求期望&#xff0c;并为功能实现提供了保护&#xff1b;开发让实现真正落地&#xff0c;满足产品功能的期望&#xff1b;重构则是为了打磨代码质量&#xff0c;降低软件的维护成本。期望—实现—改进的螺旋上升…

【力扣每日一题】力扣889根据前序和后续遍历构造二叉树

题目来源 力扣889根据前序和后续遍历构造二叉树 题目概述 给定两个整数数组&#xff0c;preorder 和 postorder &#xff0c;其中 preorder 是一个具有 无重复 值的二叉树的前序遍历&#xff0c;postorder 是同一棵树的后序遍历&#xff0c;重构并返回二叉树。 如果存在多个…

基于springboot+vue的桂林旅游景点导游平台(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Qt应用软件【协议篇】QtHttpServer三方库的编译、安装、使用示例

文章目录 1.Qt HTTP Server 简介2.主要功能和使用场景3.限制和安全性4.使用模块5.代码下载、编译与安装6.QtHttpServer代码示例1.Qt HTTP Server 简介 Qt HTTP Server 是一个轻量级的 HTTP 服务器,它允许在Qt应用程序中构建HTTP服务器功能。这个库主要用于将应用程序功能通过…

Spring Security 重点解析

Spring Security 重点解析 文章目录 Spring Security 重点解析1. 简介2. 依赖3. 登录认证3.1 登录校验流程3.2 Spring Security 默认登录的原理3.2.1 Spring Security 完整流程3.2.2 登录逻辑探究 3.3 自定义改动3.3.1 自定义用户密码校验3.3.2 自定义 UserDetails 获取方式 F1…

nginx的正向代理和反向代理

正向代理 正向代理是指客户端通过代理服务器访问互联网资源。客户端发送请求到代理服务器&#xff0c;然后由代理服务器代为向互联网资源服务器发送请求&#xff0c;并将响应返回给客户端。在这种情况下&#xff0c;互联网资源服务器并不知道请求的真实发起者是谁&#xff0c;…

基于Spring Boot的安康旅游网站的设计与实现,计算机毕业设计(带源码+论文)

源码获取地址&#xff1a; 码呢-一个专注于技术分享的博客平台一个专注于技术分享的博客平台,大家以共同学习,乐于分享,拥抱开源的价值观进行学习交流http://www.xmbiao.cn/resource-details/1760645517548793858

SpringSecurity + OAuth2 详解

SpringSecurity入门到精通 ************************************************************************** SpringSecurity 介绍 **************************************************************************一、入门1.简介与选择2.入门案例-默认的登录和登出接口3.登录经过了…

不做内容引流,你凭什么在互联网上赚钱?

孩子们放寒假了&#xff0c;待在家里不是看电视&#xff0c;就是拿着手机刷视频&#xff0c;脸上是各种欢快和满足。只是一切换到写作业模式&#xff0c;孩子是各种痛苦表情包&#xff0c;家长则是使出浑身解数&#xff0c;上演亲子大战。可见娱乐常常让人愉悦&#xff0c;而学…

Bluetooth Smart HTTP 代理服务(HTTP Proxy Service,HPS)的实现过程

在 Android 开发中,Bluetooth Smart HTTP 代理服务(HTTP Proxy Service,HPS)的实现通常涉及使用 Bluetooth GATT(通用属性)协议来进行通信。这种代理服务的实现可以让 Bluetooth Smart(低功耗蓝牙)设备通过 HTTP 代理与互联网进行通信。 下面是一个简单的示例框架,展…

cad中的快捷键

切换常规功能 CtrlG切换网格CtrlE循环等轴测平面CtrlF切换执行对象捕捉CtrlH切换拾取样式CtrlShiftH切换隐藏托盘CtrlI切换坐标CtrlShiftI切换推断约束 管理屏幕 Ctrl0&#xff08;零&#xff09;全屏显示Ctrl1“特性”选项板Ctrl2“设计中心”选项板Ctrl3“工具”选项板Ctr…

鼠标事件和滚轮事件

1. 介绍 QMouseEvent类用来表示一个鼠标事件&#xff0c;当在窗口部件中按下鼠标或者移动鼠标指针时&#xff0c;都会产生鼠标事件。利用QMouseEvent类可以获知鼠标是哪个键按下了&#xff0c;还有鼠标指针的当前位置等信息。通常是重定义部件的鼠标事件处理函数来进行一些自定…

ubuntu使用LLVM官方发布的tar.xz来安装Clang编译器

ubuntu系统上的软件相比CentOS更新还是比较快的&#xff0c;但是还是难免有一些软件更新得不那么快&#xff0c;比如LLVM Clang编译器&#xff0c;目前ubuntu 22.04版本最高还只能安装LLVM 15&#xff0c;而LLVM 18 rc版本都出来了。参见https://github.com/llvm/llvm-project/…

服务器系统日志在哪里看

查看服务器系统日志的方法取决于您使用的操作系统和服务器类型。以下是一些常见操作系统的查看系统日志的方法 在Windows操作系统中&#xff0c;可以通过“事件查看器”来查看系统日志。首先&#xff0c;点击“开始”菜单&#xff0c;选择“控制面板”&#xff0c;然后点 击“…

【STM32】Keil RTE使用记录

0 前言 最近因为任务需要&#xff0c;再次开始研究STM32&#xff0c;打算过一遍之前记录的笔记&#xff0c;在创建工程模板时&#xff0c;突然发现一个之前被自己忽略的东西&#xff0c;那就是创建项目时会弹出的Run-Time Environment&#xff0c;抱着好奇的心态去找了一些资料…

防御保护--入侵防御系统IPS

目录 DFI和DPI技术 --- 深度检测技术 入侵防御&#xff08;IPS&#xff09; 签名 入侵防御策略的配置 内容安全&#xff1a;攻击可能只是一个点&#xff0c;防御需要全方面进行 IAE引擎 DFI和DPI技术 --- 深度检测技术 DPI--深度包检测技术--主要针对完整的数据包&#xff0…

冒泡排序法的名字由来,排序步骤是什么,最坏情况下的排序次数如何计算得来的呢?

问题描述&#xff1a;冒泡排序法的名字由来&#xff0c;排序步骤是什么&#xff0c;最坏情况下的排序次数如何计算得来的呢&#xff1f; 问题解答&#xff1a; 冒泡排序法的名字来源于排序过程中较大的元素会像气泡一样逐渐“冒”到序列的顶端&#xff0c;而较小的元素则会逐…

宝玉:Sora 如何改变我们的生活

以下是宝玉老师接受有关Sora采访以及整理脱水的文字稿&#xff0c;非常值得阅读。 很荣幸受王又又邀请&#xff0c;今天和她以及《宇宙探索编辑部》副导演吕启洋&#xff08;Ash&#xff09;一起聊聊了一下当前火爆的话题 Sora&#xff0c;看 Sora 如何改变我们的生活。 我把技…