news 2026/6/10 17:38:04

太平洋大西洋水流问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
太平洋大西洋水流问题

问题

代码

#include <iostream>
#include <vector>
#include <stack>
using namespace std;
//算法思路:既能流向大西洋 ,又能流向太平洋 ,并且水往低处流
//正向寻找这样的点线会使得代码复杂,时间复杂度较大O((mn)*(mn))
//反向思路使用非递归DFS,递归DFS可能会因网格过深导致栈溢出,所以用栈模拟递归实现,更加稳定

class Solution {
private:
// 定义4个方向:上下左右(行和列的偏移量)
vector<vector<int> > dirs = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
// 存储网格的总行数和总列数
int rows, cols;

//heights 地形高度网格,visited 标记数组,记录该位置是否能到达对应海洋
//y 当前起始点的列坐标,x 当前起始点的行坐标
// 坐标合法性检查:判断(r,c)是否在网格内
bool isValid(int x ,int y) {
return x >= 0 && x < rows && y >= 0 && y < cols;
}


void dfs_iter(vector<vector<int> >& heights, int x, int y, vector<vector<bool> >& visited) {
// 用栈来模拟递归,存储待访问的坐标
stack<pair<int, int> > st;//栈的初始化 ,使得可存储坐标对类型
st.push({x, y});// 起始点入栈
visited[x][y] = true;//标记为已访问,避免重复

// 栈不为空时循环(非递归DFS的核心)
while (!st.empty()) {
// 取出栈顶元素(当前访问的坐标)
// 取出栈顶的pair对象
pair<int, int> cur = st.top();
st.pop();
// 分别赋值给cur_x和cur_y
int cur_x = cur.first;
int cur_y = cur.second;

// 遍历4个方向
for (auto& dir : dirs) {
// 计算相邻位置的坐标
int nx = cur_x + dir[0], ny = cur_y + dir[1];
// 边界条件判断:
// 1. 坐标在网格范围内
// 2. 该位置未被访问过
// 3. 相邻位置的高度 >= 当前位置高度(水往低处流,反向就是高处能流向当前处)
if (nx >= 0 && nx < rows && ny >= 0 && ny < cols && !visited[nx][ny] && heights[nx][ny] >= heights[cur_x][cur_y]) {
// 标记该位置可到达,并入栈等待后续遍历
visited[nx][ny] = true;
st.push({nx, ny});
}
}
}
}

public:
/**
* 找出既能流向太平洋又能流向大西洋的所有位置
* @param heights 地形高度网格
* @return 满足条件的坐标列表
*/
vector<vector<int> > pacificAtlantic(vector<vector<int> >& heights) {
// 存储最终结果:满足条件的坐标对
vector<vector<int> > res;
// 边界处理:如果网格为空,直接返回空结果
if (heights.empty()) return res;

// 初始化总行数和总列数
rows = heights.size(), cols = heights[0].size();
// pacific[i][j]:标记(i,j)位置的水能否流向太平洋
vector<vector<bool> > pacific(rows, vector<bool>(cols, false));
// atlantic[i][j]:标记(i,j)位置的水能否流向大西洋
vector<vector<bool>> atlantic(rows, vector<bool>(cols, false));

// 初始化边界:从太平洋的边界开始DFS
// 第一行(顶部边界)的所有位置,都能直接流向太平洋
for (int j = 0; j < cols; j++) {
dfs_iter(heights, 0, j, pacific);
// 最后一行(底部边界)的所有位置,都能直接流向大西洋
dfs_iter(heights, rows-1, j, atlantic);
}
// 初始化边界:从大西洋的边界开始DFS
// 第一列(左侧边界)的所有位置,都能直接流向太平洋
for (int i = 0; i < rows; i++) {
dfs_iter(heights, i, 0, pacific);
// 最后一列(右侧边界)的所有位置,都能直接流向大西洋
dfs_iter(heights, i, cols-1, atlantic);
}

// 补充:原代码缺失了结果收集的逻辑,这里补上
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
// 如果一个位置既能流向太平洋又能流向大西洋,加入结果
if (pacific[i][j] && atlantic[i][j]) {
res.push_back({i, j});
}
}
}

return res;
}
};
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}
};

Solution sol;
vector<vector<int>> res = sol.pacificAtlantic(heights);

cout << "===== 沿海生态保护区规划 - 关键水资源连通区域 =====" << endl;
cout << "场景说明:这些区域是海陆水资源循环的核心,对生态保护至关重要" << endl;
cout << "关键区域坐标(行, 列):" << endl;
for (auto& pos : res) {
cout << "(" << pos[0] << ", " << pos[1] << ")" << endl;
}
cout << "====================================================" << endl;

return 0;
}

思路解释

寻求既能流向太平洋又能流向大西洋的点,按照水往低处流的自然规律进行,正向解决过于复杂,时间复杂度O((mn)*(mn)),遂采取反向搜索,从边界出发,从小到大分别寻找可以流入大西洋和太平洋的点,并取两个集合的交集,保证其既能流入大西洋又能流入太平洋。因为递归DFS方法可能因为网格过深而导致溢出,所以采用栈模拟DFS方法。

先定义网格的行列,以及网格遍历周围点的移动数组并且设置循环检验点的合法化,然后定义初始化栈,并且设置起始点入栈并且进行标记,然后对不控的站进行处理:先取出栈顶元素然后重新设置一个值分别表示为取出的栈顶的点的行纵坐标经过移动的值,依次遍历取出点上下左右四个方向的点是否满足在网格内并且周围点的值大于取出点的值,然后用atlantic标记大西洋,用pacific标记太平洋,最后去两个集合的交集,得出测试结果

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/11 4:48:06

视觉盛宴:鸿蒙Canvas/Animation与Flutter CustomPaint的深度协同

前言&#xff1a;当“声明式UI”遇上“Skia引擎” 在鸿蒙Flutter的混合开发中&#xff0c;我们经常会遇到一种尴尬的局面&#xff1a;原生侧&#xff08;ArkUI&#xff09;画了一个漂亮的图表&#xff0c;Flutter侧&#xff08;Widget&#xff09;也画了一个&#xff0c;但两者…

作者头像 李华
网站建设 2026/6/10 5:09:33

钉钉机器人网关接入LobeChat对外服务能力

钉钉机器人网关接入LobeChat对外服务能力 在企业办公场景中&#xff0c;AI助手的落地常常面临一个尴尬局面&#xff1a;技术团队搭建了强大的本地大模型系统&#xff0c;但普通员工却因为要切换平台、学习新工具而望而却步。与此同时&#xff0c;几乎每个员工每天都在使用的钉钉…

作者头像 李华
网站建设 2026/6/11 2:56:34

20. 指数函数和对数函数

1.指数函数 2.对数函数 1.指数函数 1).指数函数简介a.定义: 底数固定, 指数为变量的函数b.一般形式2).指数函数的核心性质3).指数函数定理2.对数函数 1).对数函数简介a.定义: 指数函数的逆运算b.一般形式2).对数函数的性质3).对数函数定理

作者头像 李华
网站建设 2026/6/11 1:22:15

15. 纹理尺寸是4的倍数

1. 纹理尺寸是4的倍数1. 纹理尺寸是4的倍数 1).内存对齐计算机(CPU/GPU)读取内存时不是逐字节读取, 而是按固定"对齐块"(比如4字节、16 字节、64 字节)批量读取 —— 这是硬件层面的优化, 能大幅提升访问效率Unity在导入非4倍数纹理时, 即使现代GPU支持非对齐读取, 也…

作者头像 李华
网站建设 2026/6/4 20:18:41

串的练习--------统计汉字

题目&#xff1a;统计汉字-2030 代码&#xff1a; /*汉字统计 HDOJ https://acm.hdu.edu.cn/showproblem.php?pid2030*/ #include<iostream> using namespace std; int main() {char s[100000] { 0 };int n;cin >> n;getchar();//消除换行符while (n--) {fgets…

作者头像 李华
网站建设 2026/6/11 2:12:07

LobeChat快手内容推送策略

LobeChat在快手内容推送中的实践与演进 在短视频平台竞争日益激烈的今天&#xff0c;用户注意力成为最稀缺的资源。如何让用户不仅“看到内容”&#xff0c;还能“主动发现内容”&#xff1f;这是像快手这样的平台面临的核心命题。传统推荐系统依赖隐式行为数据&#xff08;如完…

作者头像 李华