图论第1天----第797题、第200题、第695题

图论第1天----第797题、第200题、第695题

文章目录

​ 又继续开始修行,把图论这块补上,估计要个5-6天时间。

一、第797题--所有可能的路径

​ 图的dfs3部曲,跟2叉树的dfs3部曲很像,分为:函数参数、终止条件、当前节点出发路径的处理(带有回溯)。下面两个是核心思路:

  • 搜索方向,是认准一个方向搜,直到碰壁之后再换方向
  • 换方向是撤销原路径,改为节点链接的下一个路径,回溯的过程。

​ 本题处理的是有向无环图,相对简单一些,我个人感觉遇到由环的图要麻烦很多,要记录路径,后面遇到的时候再看了。在外部定义一个dfs函数,再用allPathsSourceTarget去调用这个函数。

c++ 复制代码
class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;
    void dfs(vector<vector<int>>& graph, int node){
        if(node == graph.size()-1){
            result.push_back(path);
            return;
        }
        for(auto i: graph[node]){
            path.push_back(i);
            dfs(graph, i);
            path.pop_back();
        }
    }

public:
    vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
        path.push_back(0);
        dfs(graph, 0);
        return result;
    }
};

二、第200题--岛屿数量

​ 分2个函数。numIslands去找起点,从哪块算是一个岛屿的起点,并计数;dfs是根据起点遍历矩阵,找连通域,遍历连通域中每一个矩阵元素。

​ 思路上还可以,就是实现上有些麻烦。这里的dfs函数不需要定义终止条件,因为调用的函数会明确,在什么情况下调用。

c++ 复制代码
class Solution {
public:
    int dir[4][2] = {0,1,1,0,0,-1,-1,0};
    void dfs(vector<vector<char>>& grid, vector<vector<bool>>& visited, int x, int y){
        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;
            if(!visited[nextx][nexty] && grid[nextx][nexty] == '1'){
                visited[nextx][nexty] = true;
                dfs(grid, visited, nextx, nexty);
            }
        }
    }

    int numIslands(vector<vector<char>>& grid) {
        int n = grid.size();
        int m = grid[0].size();
        int result = 0;
        vector<vector<bool>> visited(n, vector<bool>(m, false));
        for(int i = 0; i<n; i++){
            for(int j = 0; j<m; j++){
                if(!visited[i][j] && grid[i][j] == '1'){
                    visited[i][j] == true;
                    result++;
                    dfs(grid, visited, i, j);
                }
            }
        }
        return result;
    }
};

广搜(bfs)是一圈一圈的搜索过程,和深搜(dfs)是一条路跑到黑然后在回溯。

广搜的搜索方式就适合于解决两个点之间的最短路径问题。

下面是广搜法(bfs)的程序,直接上答案,没有做题。通过队列去实现。bfs后面再慢慢体会吧。

c++ 复制代码
class Solution {
private:
int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 四个方向
void bfs(vector<vector<char>>& grid, vector<vector<bool>>& visited, int x, int y) {
    queue<pair<int, int>> que;
    que.push({x, y});
    visited[x][y] = true; // 只要加入队列,立刻标记
    while(!que.empty()) {
        pair<int ,int> cur = que.front(); que.pop();
        int curx = cur.first;
        int cury = cur.second;
        for (int i = 0; i < 4; i++) {
            int nextx = curx + dir[i][0];
            int nexty = cury + dir[i][1];
            if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;  // 越界了,直接跳过
            if (!visited[nextx][nexty] && grid[nextx][nexty] == '1') {
                que.push({nextx, nexty});
                visited[nextx][nexty] = true; // 只要加入队列立刻标记
            }
        }
    }
}
public:
    int numIslands(vector<vector<char>>& grid) {
        int n = grid.size(), m = grid[0].size();
        vector<vector<bool>> visited = vector<vector<bool>>(n, vector<bool>(m, false));

        int result = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (!visited[i][j] && grid[i][j] == '1') {
                    result++; // 遇到没访问过的陆地,+1
                    bfs(grid, visited, i, j); // 将与其链接的陆地都标记上 true
                }
            }
        }
        return result;
    }
};

三、第659题--岛屿的最大面积

​ 跟上一题差不多,就是把统计数量改成统计最大值,其他都一样。

c++ 复制代码
class Solution {
public:
    int dir[4][2] = {0,1,1,0,0,-1,-1,0};
    int count;
    
    void dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y){
        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;
            if(!visited[nextx][nexty] && grid[nextx][nexty] == 1){
                count++;
                visited[nextx][nexty] = true;
                dfs(grid, visited, nextx, nexty);
            }
        }
    }

    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int n = grid.size();
        int m = grid[0].size();
        int result = 0;
        vector<vector<bool>> visited(n, vector<bool>(m, false));
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                if(!visited[i][j] && grid[i][j] == 1){
                    count = 1;
                    visited[i][j] = true;
                    dfs(grid, visited, i, j);
                    //cout << 'result';
                    result = max(result, count);
                }
            }
        }
        return result;
    }
};
相关推荐
2的n次方_4 分钟前
二维费用背包问题
java·算法·动态规划
simple_ssn32 分钟前
【C语言刷力扣】1502.判断能否形成等差数列
c语言·算法·leetcode
寂静山林41 分钟前
UVa 11855 Buzzwords
算法
Curry_Math1 小时前
LeetCode 热题100之技巧关卡
算法·leetcode
ahadee1 小时前
蓝桥杯每日真题 - 第10天
c语言·vscode·算法·蓝桥杯
军训猫猫头1 小时前
35.矩阵格式的一到一百数字 C语言
c语言·算法
Mr_Xuhhh2 小时前
递归搜索与回溯算法
c语言·开发语言·c++·算法·github
SoraLuna2 小时前
「Mac玩转仓颉内测版12」PTA刷题篇3 - L1-003 个位数统计
算法·macos·cangjie
爱吃生蚝的于勒5 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
ChoSeitaku10 小时前
链表循环及差集相关算法题|判断循环双链表是否对称|两循环单链表合并成循环链表|使双向循环链表有序|单循环链表改双向循环链表|两链表的差集(C)
c语言·算法·链表