*算法训练(leetcode)第四十五天 | 101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104. 建造最大岛屿

101. 孤岛的总面积

题目地址

本题要求不与矩阵边缘相连的孤岛的总面积。先将与四个边缘相连的岛屿变为海洋,再统计剩余的孤岛的总面积。无需再标识访问过的结点,因为访问过后都变为海洋了。

时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( n 2 ) O(n^2) O(n2)

DFS

// c++
#include<bits/stdc++.h>
using namespace std;
int direction[4][2] = {0, 1, 0, -1, -1, 0, 1, 0};
int result = 0;

void pre_dfs(vector<vector<int>> &matrix, int x, int  y){
    
    matrix[x][y] = 0;
    result++;
    for(int i=0; i<4; i++){
        int nextx = x + direction[i][0];
        int nexty = y + direction[i][1];
        if(nextx>=matrix.size() || nexty>=matrix[0].size() || nextx<0 || nexty<0) continue;
        if(matrix[nextx][nexty]){
            matrix[nextx][nexty] = 0;
            
            pre_dfs(matrix, nextx, nexty);
        }
        
    }
}

int main(){
    int n,m;
    cin>>n>>m;
    vector<vector<int>> matrix(n, vector<int>(m, 0));
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>matrix[i][j];
        }
    }
    
    for(int i=0; i<n; i++) {
        if(matrix[i][0]){
            pre_dfs(matrix, i, 0);
        }
        if(matrix[i][m-1]){
            pre_dfs(matrix, i, m-1);
        }
    }
    for(int j=0; j<m; j++){
        if(matrix[0][j]){
            pre_dfs(matrix, 0, j);
        }
        if(matrix[n-1][j]){
            pre_dfs(matrix, n-1, j);   
        }
       
    }
    result = 0;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(matrix[i][j]){
                pre_dfs(matrix, i, j);   
            }
        }
    }
    cout<<result;
    return 0;
}

BFS

// c++
#include<bits/stdc++.h>
using namespace std;
int direction[4][2] = {0, 1, 0, -1, -1, 0, 1, 0};
int result = 0;

void pre_dfs(vector<vector<int>> &matrix, int x, int  y){
    
    matrix[x][y] = 0;
    result++;
    for(int i=0; i<4; i++){
        int nextx = x + direction[i][0];
        int nexty = y + direction[i][1];
        if(nextx>=matrix.size() || nexty>=matrix[0].size() || nextx<0 || nexty<0) continue;
        if(matrix[nextx][nexty]){
            matrix[nextx][nexty] = 0;
            
            pre_dfs(matrix, nextx, nexty);
        }
        
    }
}

void pre_bfs(vector<vector<int>> &matrix, int x, int  y){
    queue<pair<int, int>> que;
    que.push({x, y});
    matrix[x][y] = 0;
    result++;
    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 + direction[i][0];
            int nexty = cury + direction[i][1];
            if(nextx>=matrix.size() || nexty>=matrix[0].size() || nextx<0 || nexty<0) continue;
            if(matrix[nextx][nexty]){
                matrix[nextx][nexty] = 0;
                result++;
                que.push({nextx, nexty});
            }
        }
        
    }
}

int main(){
    int n,m;
    cin>>n>>m;
    vector<vector<int>> matrix(n, vector<int>(m, 0));
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>matrix[i][j];
        }
    }
    /*
    // dfs
    for(int i=0; i<n; i++) {
        if(matrix[i][0]){
            pre_dfs(matrix, i, 0);
        }
        if(matrix[i][m-1]){
            pre_dfs(matrix, i, m-1);
        }
    }
    for(int j=0; j<m; j++){
        if(matrix[0][j]){
            pre_dfs(matrix, 0, j);
        }
        if(matrix[n-1][j]){
            pre_dfs(matrix, n-1, j);   
        }
       
    }
    */
    // bfs
    for(int i=0; i<n; i++) {
        if(matrix[i][0]){
            pre_bfs(matrix, i, 0);
        }
        if(matrix[i][m-1]){
            pre_bfs(matrix, i, m-1);
        }
    }
    for(int j=0; j<m; j++){
        if(matrix[0][j]){
            pre_bfs(matrix, 0, j);
        }
        if(matrix[n-1][j]){
            pre_bfs(matrix, n-1, j);   
        }
       
    }
    result = 0;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(matrix[i][j]){
                // pre_dfs(matrix, i, j);   
                pre_bfs(matrix, i, j);
            }
        }
    }
    cout<<result;
    return 0;
}

102. 沉没孤岛

题目地址

本题是上一题的反向操作

先把非孤岛做访问标记,再对剩余陆地进行操作。

时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( n 2 ) O(n^2) O(n2)

DFS

// c++
#include<bits/stdc++.h>
using namespace std;
int direction[][2] = {0, 1, 0, -1, -1, 0, 1, 0};
void pre_dfs(const vector<vector<int>>& matrix,
            vector<vector<bool>>& visited,
            int x, int y){
    visited[x][y] = true;
    for(int i=0; i<4; i++){
        int nextx = x + direction[i][0];
        int nexty = y + direction[i][1];
        if(nextx>=matrix.size() || nexty>=matrix.size() ||nextx<0 || nexty<0) continue;
        if(matrix[nextx][nexty] && !visited[nextx][nexty]){
            // visited[nextx][nexty] = true;
            pre_dfs(matrix, visited, nextx, nexty);
        }
    }
}

void dfs(vector<vector<int>>& matrix,
            vector<vector<bool>>& visited,
            int x, int y){
    matrix[x][y] = 0;
    for(int i=0; i<4; i++){
        int nextx = x + direction[i][0];
        int nexty = y + direction[i][1];
        if(nextx>=matrix.size() || nexty>=matrix.size() ||nextx<0 || nexty<0) continue;
        if(matrix[nextx][nexty] && !visited[nextx][nexty]){
            visited[nextx][nexty] = true;
            dfs(matrix, visited, nextx, nexty);
        }
    }
}
int main(){
    int n,m;
    cin>>n>>m;
    vector<vector<int>> matrix(n, vector<int>(m, 0));
    vector<vector<bool>> visited(n, vector<bool>(m, false));
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>matrix[i][j];
        }
    }
    for(int i=0; i<n; i++){
        if(matrix[i][0] && !visited[i][0]) pre_dfs(matrix, visited, i, 0);
        if(matrix[i][m-1] && !visited[i][m-1]) pre_dfs(matrix, visited, i, m-1);
    }
    
    for(int j=0; j<m; j++){
        if(matrix[0][j] && !visited[0][j]) pre_dfs(matrix, visited, 0, j);
        if(matrix[n-1][j] && !visited[n-1][j]) pre_dfs(matrix, visited, n-1, j);
    }
    
    for(int i=0; i<n; i++){
        
        
        for(int j=0; j<m; j++){
            if(matrix[i][j] && !visited[i][j]){
                visited[i][j] = true;
                dfs(matrix,visited, i, j);
            }
        }
        for(int j=0; j<m; j++) cout<<matrix[i][j]<<" ";
        cout<<endl;
        
    }
    
    
    
    
    return 0;
}

BFS

//c++
#include<bits/stdc++.h>
using namespace std;
int direction[][2] = {0, 1, 0, -1, -1, 0, 1, 0};
void pre_dfs(const vector<vector<int>>& matrix,
            vector<vector<bool>>& visited,
            int x, int y){
    visited[x][y] = true;
    for(int i=0; i<4; i++){
        int nextx = x + direction[i][0];
        int nexty = y + direction[i][1];
        if(nextx>=matrix.size() || nexty>=matrix.size() ||nextx<0 || nexty<0) continue;
        if(matrix[nextx][nexty] && !visited[nextx][nexty]){
            // visited[nextx][nexty] = true;
            pre_dfs(matrix, visited, nextx, nexty);
        }
    }
}

void dfs(vector<vector<int>>& matrix,
            vector<vector<bool>>& visited,
            int x, int y){
    matrix[x][y] = 0;
    
    for(int i=0; i<4; i++){
        int nextx = x + direction[i][0];
        int nexty = y + direction[i][1];
        if(nextx>=matrix.size() || nexty>=matrix.size() ||nextx<0 || nexty<0) continue;
        if(matrix[nextx][nexty] && !visited[nextx][nexty]){
            visited[nextx][nexty] = true;
            dfs(matrix, visited, nextx, nexty);
        }
    }
}

void pre_bfs(const vector<vector<int>>& matrix,
            vector<vector<bool>>& visited,
            int x, int y){
    visited[x][y] = true;
    queue<pair<int, int>> que;
    que.push({x,y});
    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 + direction[i][0];
            int nexty = cury + direction[i][1];
            if(nextx>=matrix.size() || nexty>=matrix.size() ||nextx<0 || nexty<0) continue;
            if(matrix[nextx][nexty] && !visited[nextx][nexty]){
                visited[nextx][nexty] = true;
                que.push({nextx, nexty});
            }
        }
    }
}

void bfs(vector<vector<int>>& matrix,
            vector<vector<bool>>& visited,
            int x, int y){
    visited[x][y] = true;
    matrix[x][y] = 0;
    queue<pair<int, int>> que;
    que.push({x,y});
    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 + direction[i][0];
            int nexty = cury + direction[i][1];
            if(nextx>=matrix.size() || nexty>=matrix.size() ||nextx<0 || nexty<0) continue;
            if(matrix[nextx][nexty] && !visited[nextx][nexty]){
                visited[nextx][nexty] = true;
                matrix[nextx][nexty] = 0;
                que.push({nextx, nexty});
            }
        }
    }
}
int main(){
    int n,m;
    cin>>n>>m;
    vector<vector<int>> matrix(n, vector<int>(m, 0));
    vector<vector<bool>> visited(n, vector<bool>(m, false));
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>matrix[i][j];
        }
    }
    /*
    // dfs
    for(int i=0; i<n; i++){
        if(matrix[i][0] && !visited[i][0]) pre_dfs(matrix, visited, i, 0);
        if(matrix[i][m-1] && !visited[i][m-1]) pre_dfs(matrix, visited, i, m-1);
    }
    
    for(int j=0; j<m; j++){
        if(matrix[0][j] && !visited[0][j]) pre_dfs(matrix, visited, 0, j);
        if(matrix[n-1][j] && !visited[n-1][j]) pre_dfs(matrix, visited, n-1, j);
    }
    */
    // bfs
    for(int i=0; i<n; i++){
        if(matrix[i][0] && !visited[i][0]) pre_bfs(matrix, visited, i, 0);
        if(matrix[i][m-1] && !visited[i][m-1]) pre_bfs(matrix, visited, i, m-1);
    }
    
    for(int j=0; j<m; j++){
        if(matrix[0][j] && !visited[0][j]) pre_bfs(matrix, visited, 0, j);
        if(matrix[n-1][j] && !visited[n-1][j]) pre_bfs(matrix, visited, n-1, j);
    }
    
    for(int i=0; i<n; i++){
        
        
        for(int j=0; j<m; j++){
            if(matrix[i][j] && !visited[i][j]){
                // visited[i][j] = true;
                // dfs(matrix,visited, i, j);
                bfs(matrix,visited, i, j);
            }
        }
        for(int j=0; j<m; j++) cout<<matrix[i][j]<<" ";
        cout<<endl;
        
    }
    
    
    
    
    return 0;
}

*103. 水流问题

题目地址

使用两个标识访问的数组分别从两组边界出发进行dfs遍历,使用从低向高流(反向流)来分别记录两组边界的结点。最后两组边界的交集就是本题答案。
思路

时间复杂度: O ( m ∗ n ) O(m*n) O(mn)
空间复杂度: O ( m ∗ n ) O(m*n) O(mn)

// c++
#include<bits/stdc++.h>
using namespace std;
int direction[][2] = {0, 1, 0, -1, -1, 0, 1, 0};
void dfs(const vector<vector<int>> &matrix, 
        vector<vector<bool>> &visited,
        int x, int y){
    visited[x][y] = true;
    
    for(int i=0; i<4; i++){
        int nextx = x + direction[i][0];
        int nexty = y + direction[i][1];
        if(nextx>=matrix.size() || nexty>=matrix[0].size() || nextx<0 || nexty<0) continue;
        if(matrix[x][y]>matrix[nextx][nexty]) continue;
        if(!visited[nextx][nexty]) dfs(matrix, visited, nextx, nexty);
    }
}

int main(){
    int n,m;
    cin>>n>>m;
    vector<vector<int>> matrix(n, vector<int>(m, 0));
    vector<vector<bool>> first(n, vector<bool>(m, false));
    vector<vector<bool>> second(n, vector<bool>(m, false));
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>matrix[i][j];
        }
    }
    
    for(int i=0; i<n; i++){
        dfs(matrix, first, i, 0);
        dfs(matrix, second, i, m-1);
    }
    for(int j=0; j<m; j++){
        dfs(matrix, first, 0, j);
        dfs(matrix, second, n-1, j);
    }
    
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(first[i][j] && second[i][j]) cout<<i<<" "<<j<<endl;
        }
    }
    
    return 0;   
}

*104. 建造最大岛屿

题目地址

分两阶段。

  1. 先对地图中的陆地进行一次遍历,对每一个岛屿进行标记,同时计算每个岛屿的面积。
  2. 再对地图中的水域进行一次遍历,计算每一个水域变成陆地后的连续陆地面积,就是把水域四个方向的陆地面积求和,再加上1表示当前水域变为陆地。

题解

时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( n 2 ) O(n^2) O(n2)

// c++
#include<bits/stdc++.h>
using namespace std;
int direction[4][2] = {0, 1, 0, -1, -1, 0, 1, 0};

void dfs(vector<vector<int>> &matrix, 
        vector<vector<bool>> &visited, 
        int x, int  y, int &count, int mark){
    visited[x][y] = true;
    matrix[x][y] = mark;
    count++;
    
    for(int i=0; i<4; i++){
        int nextx = x + direction[i][0];
        int nexty = y + direction[i][1];

        if(nextx>=matrix.size() || nexty>=matrix[0].size() || nextx<0 || nexty<0) continue;
        if(matrix[nextx][nexty] == 1 && !visited[nextx][nexty]){
            dfs(matrix, visited, nextx, nexty, count, mark);
        }
    }
}

int main(){
    int n,m;
    cin>>n>>m;
    vector<vector<int>> matrix(n, vector<int>(m, 0));
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>matrix[i][j];
        }
    }
    vector<vector<bool>> visited(n, vector<bool>(m, false));
    // 记录岛屿面积
    unordered_map<int, int> markCount;
    int mark = 2;
    int count;
    bool isAllGrid = true;
    // 第一阶段:记录岛屿大小
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(matrix[i][j] == 0) isAllGrid = false;
            if(matrix[i][j] == 1 && !visited[i][j]){
                count = 0;
                dfs(matrix, visited, i, j, count, mark);
                markCount[mark] = count;
                mark++;
            }
        }
    }
    if(isAllGrid) {
        cout<<n*m<<endl;
        return 0;
    }
    int result = 0;
    // 第二阶段
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            // 非陆地 计算把当前水域变为陆地的最大面积
            if(matrix[i][j] == 0){
                unordered_set<int> lands;
                // 把当前水域变为陆地
                count = 1;
                // 遍历当前水域的四个方向 把四个方向的陆地面积都加起来
                for(int k=0; k<4; k++){
                    int nextx = i + direction[k][0];
                    int nexty = j + direction[k][1];
                    if(nextx>=matrix.size() || nexty>=matrix[0].size() || nextx<0 || nexty<0) continue;
                    // 当前陆地已加入
                    if(lands.count(matrix[nextx][nexty])>0) continue;
                    
                    count += markCount[matrix[nextx][nexty]];
                    // 标记已加入的节点
                    lands.insert(matrix[nextx][nexty]);
                }
            }
            
            result = max(result, count);
        }
    }
    cout<<result;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值