63日目 コードカプリスアルゴリズム合宿(19) グラフ理論 その2

1020. 飛び地の数

分析: 国境に囲まれていない陸塊の数を見つけます。
アイデア 1: 深さ優先トラバーサル
  • まず 4 つの側面から陸地を探し、次に深さ優先トラバースを実行して、隣接するすべての陸地 (1) を海洋 (0) に変換します。
    • 深さ優先トラバーサル: 4 方向からの再帰的トラバーサル
  • グラフ全体を横断し、すべての陸塊の数を数えます。
class Solution {
public:
    int direct[4][2]={
   
   {0,1},{0,-1},{1,0},{-1,0}};
    int res=0;
    void dfs(vector<vector<int>>&grid,int x,int y){
        grid[x][y]=0;
        for(int i=0;i<4;i++){
            int nextx=x+direct[i][0];
            int nexty=y+direct[i][1];
            if(nextx>=0 && nextx<grid.size() && nexty>=0 && nexty<grid[0].size()){//边界条件
                if(grid[nextx][nexty]==1){
                    grid[nextx][nexty]=0;
                    dfs(grid,nextx,nexty);
                }
            }
        }
    }
    int numEnclaves(vector<vector<int>>& grid) {
        int n=grid.size(),m=grid[0].size();
        for(int i=0;i<n;i++){
            if(grid[i][0]==1) dfs(grid,i,0);//左侧边
            if(grid[i][m-1]==1) dfs(grid,i,m-1);//右侧边
        }
        for(int j=0;j<m;j++){
            if(grid[0][j]==1) dfs(grid,0,j);//上侧边
            if(grid[n-1][j]==1) dfs(grid,n-1,j);//下侧边
        }
        for(int i=1;i<n-1;i++){//遍历整个图
            for(int j=1;j<m-1;j++){
                if(grid[i][j]==1) res++;
            }
        }
        return res;
    }
};

130. 周囲のエリア

アイデア 1: DFS
  • まだ陸地の深さを最初に4つの側面から横断​​し、それからAの文字に変更します
  • 次に、グラフ全体を横断して、残りの陸地 (海水に包まれている必要があります) を海水に変更し、A の文字を陸地に変更します。
class Solution {
public:
    int direct[4][2]={
   
   {0,1},{0,-1},{1,0},{-1,0}};
    int res=0;
    void dfs(vector<vector<char>>&board,char target,int x,int y)
    {
        board[x][y]=target;
        res++;
        for(int i=0;i<4;i++){
            int nextx=x+direct[i][0];
            int nexty=y+direct[i][1];
            if(nextx>=0 && nextx<board.size() && nexty>=0 && nexty<board[0].size()){
                if(board[nextx][nexty]=='O'){
                    board[nextx][nexty]=target;
                    dfs(board,target,nextx,nexty);
                }
            }
        }
    }
    void solve(vector<vector<char>>& board) {

        int n=board.size(),m=board[0].size();
        for(int i=0;i<n;i++){
            if(board[i][0]=='O') dfs(board,'A',i,0);//左侧边
            if(board[i][m-1]=='O') dfs(board,'A',i,m-1);//右侧边
        }
        for(int j=0;j<m;j++){
            if(board[0][j]=='O') dfs(board,'A',0,j);//上侧边
            if(board[n-1][j]=='O') dfs(board,'A',n-1,j);//下侧边
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(board[i][j]=='A') board[i][j]='O';//所有的A变为O
                else if(board[i][j]=='O') board[i][j]='X';//所有的O变为X
            }
        } 
    }
};

417. 太平洋と大西洋の水の流れの問題

アイデア 1: 深さ優先トラバーサル
  • 2 つのアレイがそれぞれ大西洋側と太平洋側から取得されます。
  • 両方の配列が同じ位置を通過する場合、それは両側に流れることができることを意味します。
class Solution {
public:
    int direct[4][2]={
   
   {1,0},{-1,0},{0,1},{0,-1}};
    void dfs(vector<vector<int>>&heights,vector<vector<bool>>&visted,int x,int y){
        if(visted[x][y]) return;
        visted[x][y]=true;
        for(int i=0;i<4;i++){
            int nextx=x+direct[i][0];
            int nexty=y+direct[i][1];
            if(nextx>=0 && nextx<heights.size() && nexty>=0 && nexty<heights[0].size()){
                if(heights[x][y]<=heights[nextx][nexty])//本来是从高到低,这是倒着推,所以低到高
                    dfs(heights,visted,nextx,nexty);
            }
        }
    }
    vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
        int n=heights.size(),m=heights[0].size();
        vector<vector<int>>res;

        vector<vector<bool>>pacific(n,vector<bool>(m,false));//太平洋
        vector<vector<bool>>atlantic(n,vector<bool>(m,false));//大西洋

        for(int i=0;i<n;i++){
            dfs(heights,pacific,i,0);//从左侧太平洋出发
            dfs(heights,atlantic,i,m-1);//从右侧大西洋出发
        }

        for(int j=0;j<m;j++){
            dfs(heights,pacific,0,j);//从上侧太平洋出发
            dfs(heights,atlantic,n-1,j);//从下侧大西洋出发
        }

        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(pacific[i][j] && atlantic[i][j])//从大西洋和太平洋都可以流过
                    res.push_back({i,j});
            }
        }
        return res;
    }
};

おすすめ

転載: blog.csdn.net/Ricardo_XIAOHAO/article/details/133444385