先来看一下题目描述:

305. Number of Islands II

A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand operation which turns the water at position (row, col) into a land. Given a list of positions to operate, count the number of islands after each addLand operation. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

Example:

Input: m = 3, n = 3, positions = [[0,0], [0,1], [1,2], [2,1]]
Output: [1,1,2,3]

Explanation:

Initially, the 2d grid grid is filled with water. (Assume 0 represents water and 1 represents land).

0 0 0
0 0 0
0 0 0

Operation #1: addLand(0, 0) turns the water at grid[0][0] into a land.

1 0 0
0 0 0   Number of islands = 1
0 0 0

Operation #2: addLand(0, 1) turns the water at grid[0][1] into a land.

1 1 0
0 0 0   Number of islands = 1
0 0 0

Operation #3: addLand(1, 2) turns the water at grid[1][2] into a land.

1 1 0
0 0 1   Number of islands = 2
0 0 0

Operation #4: addLand(2, 1) turns the water at grid[2][1] into a land.

1 1 0
0 0 1   Number of islands = 3
0 1 0

Follow up:

Can you do it in time complexity O(k log mn), where k is the length of the positions?

那么 先放上我写的代码:

//每次在指定位置将0变成1,之后返回islands的数目
//考虑从1开始上色,如果当前位置的四周有相邻的,直接进行相连即可,否则上的颜色+1
//题目里面可能会给重复上色的区域
class Solution {
public:
    vector<int> numIslands2(int m, int n, vector<vector<int>>& positions) {
        vector<vector<int>> grid(m,vector<int>(n,0)); //grid网格
        for(auto pos:positions){
            int x=pos[0],y=pos[1]; //当前添加点的坐标
            if(color.size()==0){ //第一次的话,肯定需要进行赋值
                grid[x][y]=1;
                color.insert(1);
                res.push_back(1);
                for_record=1;
                continue;
            }
            int min_color=min(min(check(grid,x-1,y),check(grid,x+1,y)),min(check(grid,x,y-1),check(grid,x,y+1)));
            if(min_color==INT_MAX && grid[x][y]==0){ //如果未进行过上色,继续上色,这里要判重复值!
                grid[x][y]=++for_record; //记录颜色先来进行增加
                color.insert(grid[x][y]);
                res.push_back(color.size());
            }
            else{ //否则我们以最小颜色进行修改
                grid[x][y]=min_color;
                dfs(grid,x-1,y,min_color);
                dfs(grid,x+1,y,min_color);
                dfs(grid,x,y-1,min_color);
                dfs(grid,x,y+1,min_color);
                res.push_back(color.size());
            }
        }
        return res;
    }
private:
    set<int> color; //记录使用的颜色
    vector<int> res; //最终结果
    int for_record=0; //记录颜色,如果仅仅按照color的size的话可能会出现重复值
    
    int check(vector<vector<int>>& grid,int x,int y){
        if(!isValid(grid,x,y) || grid[x][y]==0) //超出边界或者未上色
            return INT_MAX;
        return grid[x][y]; //否则返回之前的上色值
    }

    bool isValid(vector<vector<int>>& grid,int x,int y){
        if(x<0 || x>=grid.size() || y<0 || y>=grid[0].size())
            return false;
        return true;
    }
    
    void dfs(vector<vector<int>>& grid,int x,int y,int c){
        if(!isValid(grid,x,y) || grid[x][y]==0) //超出边界
            return;
        if(grid[x][y]==c) //进行过上色的返回
            return;
        if(grid[x][y]!=0 && grid[x][y]!=c){ //碰到了之前上其他颜色的,进行修改
            if(color.count(grid[x][y])) //把原来的颜色删除
                color.erase(grid[x][y]);
            grid[x][y]=c;
        }
        dfs(grid,x+1,y,c);
        dfs(grid,x-1,y,c);
        dfs(grid,x,y-1,c);
        dfs(grid,x,y+1,c);
    }
};

在做题当中的几个问题:

现在对于dfs的小岛问题,有点喜欢用上色来做,并且很多时候可以用一个set来记录使用过的颜色

1.对于这道题,一开始也是相同的思路,我想用set.size()来直接进行记录更新颜色,但是总是WA,想了一下,因为我在改变颜色的时候,如果仅仅使用set.size(),无法避免重复值的产生,可能明明不想连的两块,由于颜色大小的改变,同时变成了相同的颜色,这是不允许的!!!因此我再增加一个变量for_record来进行记录颜色,这样可以保证颜色永远不会重复!