• 算法|图论 5


    LeetCode 841- 钥匙和房间

    题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

    题目描述:有 n 个房间,房间按从 0 到 n - 1 编号。最初,除 0 号房间外的其余所有房间都被锁住。你的目标是进入所有的房间。然而,你不能在没有获得钥匙的时候进入锁住的房间。

    当你进入一个房间,你可能会在里面找到一套不同的钥匙,每把钥匙上都有对应的房间号,即表示钥匙可以打开的房间。你可以拿上所有钥匙去解锁其他房间。

    给你一个数组 rooms 其中 rooms[i] 是你进入 i 号房间可以获得的钥匙集合。如果能进入 所有 房间返回 true,否则返回 false。

    解题思路(广度优先遍历):

    这题需要注意,本题是一道有向图的题,前面的题基本上都是无向图。首先,将第一个房间的钥匙进队,然后当队列不为空时,不断出队。打开对应的门,拿钥匙,如果之前这个门已经开过了。就直接continue。否则就将这个钥匙能开的门入队。

    1. class Solution {
    2. public:
    3. bool canVisitAllRooms(vector<vector<int>>& rooms) {
    4. vector<bool> visited(rooms.size(),false);//来记录我们能打开的门
    5. queue<vector<int>> que;//存储能打开的门的钥匙组
    6. que.push(rooms[0]);
    7. while(!que.empty()){
    8. vector<int> tmp = que.front();
    9. que.pop();
    10. for(int i=0;i<tmp.size();i++){
    11. if(visited[tmp[i]] == false){//若这门被开过了,直接跳过,不然可能会死循环
    12. que.push(rooms[tmp[i]]);
    13. visited[tmp[i]] = true;
    14. }
    15. }
    16. }
    17. for(int i=1;i<rooms.size();i++){
    18. if(visited[i] == false) return false;
    19. }
    20. return true;
    21. }
    22. };

    总结:

    • 一道简单的有向图,主要是不要重复去开同一个门。思路还是比较简单的。

    LeetCode 463- 岛屿的周长

    题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

    题目描述:给定一个 row x col 的二维网格地图 grid ,其中:grid[i][j] = 1 表示陆地, grid[i][j] = 0 表示水域。

    网格中的格子 水平和垂直 方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。

    岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。

    解题思路

    思路一:

    遍历所有的格子,首先判断不是陆地就continue,是陆地我们就对其四个方向进行侦测,若是海洋或边界则说明这个方向对应的有一个边可以当作周长加上。即res++。

    1. class Solution {
    2. public:
    3. int direction[4][2] = {0, 1, 1, 0, -1, 0, 0, -1};
    4. int islandPerimeter(vector<vector<int>>& grid) {
    5. int result = 0;
    6. for (int i = 0; i < grid.size(); i++) {
    7. for (int j = 0; j < grid[0].size(); j++) {
    8. if (grid[i][j] == 1) {
    9. for (int k = 0; k < 4; k++) { // 上下左右四个方向
    10. int x = i + direction[k][0];
    11. int y = j + direction[k][1]; // 计算周边坐标x,y
    12. if (x < 0 // i在边界上
    13. || x >= grid.size() // i在边界上
    14. || y < 0 // j在边界上
    15. || y >= grid[0].size() // j在边界上
    16. || grid[x][y] == 0) { // x,y位置是水域
    17. result++;
    18. }
    19. }
    20. }
    21. }
    22. }
    23. return result;
    24. }
    25. };

    思路二:

    通过观察可以看出来,只要有一对岛屿挨在一起,那么其总周长就应该减2。故我们只需要判断当前点是否有挨着岛屿即可,有则面积-2。注意,我们只需要讨论 左边和上边右边和下边 即可。因为会遍历所有的岛屿,防止重复遍历了。

    1. class Solution {
    2. public:
    3. int islandPerimeter(vector<vector<int>>& grid) {
    4. int sum = 0; // 陆地数量
    5. int cover = 0; // 相邻数量
    6. for (int i = 0; i < grid.size(); i++) {
    7. for (int j = 0; j < grid[0].size(); j++) {
    8. if (grid[i][j] == 1) {
    9. sum++;
    10. // 统计上边相邻陆地
    11. if(i - 1 >= 0 && grid[i - 1][j] == 1) cover++;
    12. // 统计左边相邻陆地
    13. if(j - 1 >= 0 && grid[i][j - 1] == 1) cover++;
    14. // 为什么没统计下边和右边? 因为避免重复计算
    15. }
    16. }
    17. }
    18. return sum * 4 - cover * 2;
    19. }
    20. }

    总结:

    • 开始自己想的是广度优先,每次遍历的时候再判断每个点的四周,没想到这么简单的思路就可以了。因为我们不需要求多个岛屿。只有一个岛屿,所以可以这样。若是求多个岛屿的周长,那可能就需要广度优先加判断了。
  • 相关阅读:
    Error: [vuex] do not mutate vuex store state outside mutation handlers.
    PHP8中查询数组中指定元素-PHP8知识详解
    【树莓派不吃灰】搭建emqx MQTT Broker
    超详细的zookeeper和hbase安装教程以及启动脚本zk.sh等
    这 6 款在线 PDF 转换工具,得试试
    计算机三级信息安全笔记(知识点)
    1712A 300A嵌入式电源系统
    FIR与IIR数字滤波器的比较
    Java修仙之高级功法篇->MybatisPlus
    重读 Java 设计模式: 探索经典之道与 Spring 框架的设计
  • 原文地址:https://blog.csdn.net/m0_47893709/article/details/132902030