首页 > 其他分享 >图论基础|417. 太平洋大西洋水流问题、827.最大人工岛、127. 单词接龙

图论基础|417. 太平洋大西洋水流问题、827.最大人工岛、127. 单词接龙

时间:2024-03-22 23:30:29浏览次数:26  
标签:visited vector int 岛屿 heights 417 grid 127 接龙

目录

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

827.最大人工岛

127. 单词接龙


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

题目链接(opens new window)

有一个 m × n 的矩形岛屿,与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界,而 “大西洋” 处于大陆的右边界和下边界。

这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n 的整数矩阵 heights , heights[r][c] 表示坐标 (r, c) 上单元格 高于海平面的高度 。

岛上雨水较多,如果相邻单元格的高度 小于或等于 当前单元格的高度,雨水可以直接向北、南、东、西流向相邻单元格。水可以从海洋附近的任何单元格流入海洋。

返回网格坐标 result 的 2D 列表 ,其中 result[i] = [ri, ci] 表示雨水从单元格 (ri, ci) 流动 既可流向太平洋也可流向大西洋 。

示例 1:

  • 输入: 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]]

提示:

  • m == heights.length
  • n == heights[r].length
  • 1 <= m, n <= 200
  • 0 <= heights[r][c] <= 10^5

思路:

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

从太平洋边上节点出发,如图:

图一

从大西洋边上节点出发,如图:

图二

class Solution {
public:
    //dfs版
    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);
            // visited[nextx][nexty]=true;
        }
        return;

    }
    vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
        int n=heights.size();//列数
        int m=heights[0].size();//行数
        vector<vector<bool>>pacificVisited(n,vector<bool>(m,false));
        vector<vector<bool>>atlanticVisited(n,vector<bool>(m,false));
        //从边上分别遍历
        for(int i=0;i<n;i++){
            dfs(heights, pacificVisited, i,0);//遍历最顶上
            dfs(heights,atlanticVisited,i,m-1);//遍历最底下
        }

        for(int j=0;j<m;j++){
            dfs(heights, pacificVisited, 0, j);//遍历最左边
            dfs(heights, atlanticVisited, n-1,j); //遍历最右边
        }
        vector<vector<int>>result;
        //遍历整个地图
        for(int i=0;i<n;i++){
            for(int j=0; j<m;j++){
                if(pacificVisited[i][j]&&atlanticVisited[i][j]){
                    result.push_back({i,j});
                }
            }
        }
        return result;

    }
};

827.最大人工岛

力扣链接(opens new window)

给你一个大小为 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。

思路:

只要用一次深搜把每个岛屿的面积记录下来就好。

第一步:一次遍历地图,得出各个岛屿的面积,并做编号记录。可以使用map记录,key为岛屿编号,value为岛屿面积 第二步:在遍历地图,遍历0的方格(因为要将0变成1),并统计该1(由0变成的1)周边岛屿面积,将其相邻面积相加在一起,遍历所有 0 之后,就可以得出 选一个0变成1 之后的最大面积。

class Solution {
private:
    int count;
    int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 四个方向
    void dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y, int mark) {
        if (visited[x][y] || grid[x][y] == 0) return; // 终止条件:访问过的节点 或者 遇到海水
        visited[x][y] = true; // 标记访问过
        grid[x][y] = mark; // 给陆地标记新标签
        count++;
        for (int i = 0; i < 4; i++) {
            int nextx = x + dir[i][0];
            int nexty = y + dir[i][1];
            if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;  // 越界了,直接跳过
            dfs(grid, visited, nextx, nexty, mark);
        }
    }

public:
    int largestIsland(vector<vector<int>>& grid) {
        int n = grid.size(), m = grid[0].size();
        vector<vector<bool>> visited = vector<vector<bool>>(n, vector<bool>(m, false)); // 标记访问过的点
        unordered_map<int ,int> gridNum;
        int mark = 2; // 记录每个岛屿的编号
        bool isAllGrid = true; // 标记是否整个地图都是陆地
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (grid[i][j] == 0) isAllGrid = false;
                if (!visited[i][j] && grid[i][j] == 1) {
                    count = 0;
                    dfs(grid, visited, i, j, mark); // 将与其链接的陆地都标记上 true
                    gridNum[mark] = count; // 记录每一个岛屿的面积
                    mark++; // 记录下一个岛屿编号
                }
            }
        }
        if (isAllGrid) return n * m; // 如果都是陆地,返回全面积

        // 以下逻辑是根据添加陆地的位置,计算周边岛屿面积之和
        int result = 0; // 记录最后结果
        unordered_set<int> visitedGrid; // 标记访问过的岛屿
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                int count = 1; // 记录连接之后的岛屿数量
                visitedGrid.clear(); // 每次使用时,清空
                if (grid[i][j] == 0) {
                    for (int k = 0; k < 4; k++) {
                        int neari = i + dir[k][1]; // 计算相邻坐标
                        int nearj = j + dir[k][0];
                        if (neari < 0 || neari >= grid.size() || nearj < 0 || nearj >= grid[0].size()) continue;
                        if (visitedGrid.count(grid[neari][nearj])) continue; // 添加过的岛屿不要重复添加
                        // 把相邻四面的岛屿数量加起来
                        count += gridNum[grid[neari][nearj]];
                        visitedGrid.insert(grid[neari][nearj]); // 标记该岛屿已经添加过
                    }
                }
                result = max(result, count);
            }
        }
        return result;
    }
};

127. 单词接龙

力扣题目链接(opens new window)

字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列:

  • 序列中第一个单词是 beginWord 。
  • 序列中最后一个单词是 endWord 。
  • 每次转换只能改变一个字母。
  • 转换过程中的中间单词必须是字典 wordList 中的单词。
  • 给你两个单词 beginWord 和 endWord 和一个字典 wordList ,找到从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0。

示例 1:

  • 输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
  • 输出:5
  • 解释:一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。

示例 2:

  • 输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
  • 输出:0
  • 解释:endWord "cog" 不在字典中,所以无法进行转换

思路:最短路径,考虑广度优先搜索;为了提升查找效率,可以采用哈希结构,将单词列表转换到unodered_set,将路径与长度放到unodered_map<string, int>里;每次查找时,用两个for循环,一个for循环遍历beginword进行字母替换,另一个循环遍历26个字母,依次进行替换,再看看替换后字母有没有出现在单词集合unodered_set里,如果出现了:假如正好==endword,路径长度+1,返回结果;否则路径长度+1,继续进行搜索

class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        unordered_set<string>wordset(wordList.begin(), wordList.end());
        if(wordset.find(endWord)==wordset.end())return 0;

        unordered_map<string,int> visitedmap;//记录单词及对应路径长度

        queue<string>que;
        que.push(beginWord);
        visitedmap.insert(pair<string,int>(beginWord,1));//第一个单词,路径1
        while(!que.empty()){
            string word=que.front(); que.pop();
            int pathlen=visitedmap[word];
            for(int i=0;i<word.size();i++){
                string newword=word;
                for(int j=0;j<26;j++){
                    newword[i]=j+'a';
                    if(newword==endWord)return pathlen+1;
                    //判断新字符串是否在单词集合里面,如果在,说明有效;
                    //再看新单词是否在路径集合里出现过,如果有效且未出现在路径里,那么加入路径,路径长度+1,继续2迭代
                    if(wordset.find(newword)!=wordset.end()&&visitedmap.find(newword)==visitedmap.end()){
                        visitedmap.insert(pair<string,int>(newword,pathlen+1));
                        que.push(newword);
                    }

                }
            }
        }
        return 0;
    }
};

 参考:代码随想录

标签:visited,vector,int,岛屿,heights,417,grid,127,接龙
From: https://blog.csdn.net/qq_60513199/article/details/136946116

相关文章

  • 解决 [FATAL] plugin/loop: Loop (127.0.0.1:49443 -> :53) detected for zone "." 报
    问题背景:这个是安装k8s时报的错,安装使用的是ubuntu系统,当安装到coredns时报如下错 解决方法:查找了一番资料,得出结论这个算是ubuntu和k8scoredns安装的一个兼容性问题,不过很好解决,参照coredns官方文档就可以~首先贴出官网:https://coredns.io/plugins/loop/#troubleshooting......
  • 龙行龘龘,成语接龙,祝您龙年大吉
    先祝大家新的一年:龙行龘龘,前程朤朤!龙年当然要玩成语接龙啦!这是龙的传承与创新(话说龙辰辰真的好可爱哇)成语接龙游戏规则:必须是成语;除了第一个,后面每次接龙的成语必须是前一个成语的最后一个字相同的拼音。管你听没听懂,玩就完了!1.龙年主题界面共有五个功能,设计的功能......
  • 洛谷 P4173 残缺的字符串 卡常小记
    首先,使用匹配函数\(P(x_i,x_j)=x_ix_j-x_i^2[j\neq0]\)。容易发现,当存在\(i\neqj\)时,\(x_ix_j\)的系数只会增加,因此根据Schwartz-Zippel引理,随机一组\(x_{1\sim26}\)对应a~z即可。然后,对于NTT的过程,有两个卡常的点:一是点积reverse后转卷积的过程是舍......
  • 丹麦振动传感器PCH1270/CHF8298/L10M
    丹麦振动传感器是一种用于检测和测量物体振动的设备。它通常由一个敏感元件和一个信号处理器组成。敏感元件可以是压电晶体、电阻式传感器或加速度计等,用于将振动转换为电信号。信号处理器则负责对接收到的信号进行放大、滤波和解码等处理,以便得到有关振动的相关信息。丹麦......
  • Error running 'Tomcat 8.5.27': Unable to open debugger port (127.0.0.1:2887): ja
    火绒安全-导致的tomcat8启动异常 一、问题由来最近有个朋友在学习使用IDEA配置tomcat8.5.99的时候,使用一切都正常,直到学习到使用Servlet实现文件下载功能的时候,出现问题。写了一个简单的Servlet用来测试文件下载,直接把路径放在浏览器中测试的时候,可以正常下载。可是不......
  • 一本通 1270 混合背包 题解
    是在hydro上做的,墙裂推荐hydro的一本通题库!链接是:https://hydro.ac/d/ybttk/p/T1270。分析一下,可以分类讨论,处理的时候,零一背包(\(p_i=1\))一个,完全背包(\(p_i=0\))一个,多重背包(\(p_i>1\))一个,状态转移方程不用列的,直接去抄模板就可以啦~代码是这样的捏:#include<bits/st......
  • arc127A 分巧克力
    题面:有一块大小为H*W的巧克力,要分给n个人,第i个人要分边长为2^a[i]的正方形,问是否够分?范围:H,W<=1E9;n<=1000;a[i]<=25思路:贪心,关键是先处理大请求,并且要用大块来处理大请求。将请求按从大到小依次处理,优先处理大请求,如果处理不了,则无解。用大根堆维护剩余的巧克力大小,按短边......
  • 解决 Android studio Connect to 127.0.0.1:[/127.0.0.1] failed: Connection refused
    前言由于代理变更,androidstudio会有一系列报错,其中一个是Connectto127.0.0.1:xxxxxx[/127.0.0.1]failed:Connectionrefused网上答案大都太片面了,无法完全解决问题,这里列举出四个可能的原因,希望对大家有用问题如下建议一下四种方案都尝试下,我相信总有一种能......
  • 洛谷题单指南-搜索-P1019 [NOIP2000 提高组] 单词接龙
    原题链接:https://www.luogu.com.cn/problem/P1019题意解读:要计算接龙能得到的最长字符串,可以通过DFS暴搜所有可能的接龙方案解题思路:DFS的关键在于两个判断:1、下一个单词是否可以和上一个单词接龙,最短公共长度是多少(只需要看两个单词的最短公共长度,这样能保证接龙更长)2、单词......
  • 1277. 维护序列
    #include<iostream>#include<stdio.h>#include<algorithm>#include<string>#defineFor(i,j,n)for(inti=j;i<=n;++i)usingnamespacestd;typedeflonglongLL;constintN=1e5+5;intn,m,P,a[N];structnod......