LintCode 897: Island City

897. Island City

Given a matrix of size n x m, the elements in the matrix are 0、1、2. 0 for the sea, 1 for the island, and 2 for the city on the island(You can assume that 2 is built on 1, ie 2 also represents the island).

If two 1 are adjacent, then these two 1 belong to the same island. Find the number of islands with at least one city.

 

Example

Example1

 

Input: 

[

[1,1,0,0,0],

[0,1,0,0,1],

[0,0,0,1,1],

[0,0,0,0,0],

[0,0,0,0,1]

]

Output: 0

Explanation:

There are 3 islands, but none of them contain cities.

Example2

 

Input: 

[

[1,1,0,0,0],

[0,1,0,0,1],

[0,0,2,1,2],

[0,0,0,0,0],

[0,0,0,0,2]

]

Output: 2

Explanation:

There are 3 islands, and two of them have cities.

Notice

We only consider up, down, left and right as adjacent.

n <= 100,m <= 100.

You can assume that the four sides of the matrix are surrounded by the sea.

解法1:BFS

注意 grid[curNode.first][curNode.second] = 0 要在for循环前面执行,不然for 循环里面又碰到它是1或2的时候就出错了。

class Solution {
public:
    /**
     * @param grid: an integer matrix
     * @return: an integer 
     */
    int numIslandCities(vector<vector<int>> &grid) {
        int nRow = grid.size();
        int nCol = grid[0].size();
        
        int result = 0;
        for (int i = 0; i < nRow; ++i) {
            for (int j = 0; j < nCol; ++j) {
                if (grid[i][j] == 0) continue;
                if (bfs(grid, i, j)) result++;
            }
        }
        
        return result;
    }
    
private:
    //return true if it has island and the island has city
    bool bfs(vector<vector<int>> &grid, int x, int y) {
        int nRow = grid.size();
        int nCol = grid[0].size();
        bool result = false;
        
        vector<int> dx = {0, 0, 1, -1};
        vector<int> dy = {1, -1, 0, 0};
        
        queue<pair<int, int>> q;
        q.push({x, y});
        
        while(!q.empty()) {
            auto curNode = q.front();
            q.pop();
            if (grid[curNode.first][curNode.second] == 2) result = true;
            grid[curNode.first][curNode.second] = 0;
            for (int i = 0; i < 4; ++i) {
                int newX = curNode.first + dx[i];
                int newY = curNode.second + dy[i];
                if (newX < 0 || newX >= grid.size() || newY < 0 || newY >= grid[0].size() || grid[newX][newY] == 0) continue;
                q.push({newX, newY});
            }
        }
        
        return result;
    }
};

解法2:DFS

class Solution {
public:
    /**
     * @param grid: an integer matrix
     * @return: an integer 
     */
    int numIslandCities(vector<vector<int>> &grid) {
        int nRow = grid.size();
        int nCol = grid[0].size();
        
        int result = 0;
        for (int i = 0; i < nRow; ++i) {
            for (int j = 0; j < nCol; ++j) {
   
                int count = 0;
                if (grid[i][j] != 0) {
                    dfs(grid, i, j, count);
                    if (count > 0) result++;
                }
            }
        }
        return result;
    }
    
private:
    void dfs(vector<vector<int>> &grid, int x, int y, int & count) {
        int nRow = grid.size();
        int nCol = grid[0].size();
        bool result = false;
        
        if (x < 0 || x >= nRow || y < 0 || y >= nCol || grid[x][y] == 0)
            return;
        
        if (grid[x][y] == 2) {
            count++;
        }
        grid[x][y] = 0;
        
        vector<int> dx = {0, 0, 1, -1};
        vector<int> dy = {1, -1, 0, 0};

        for (int i = 0; i < 4; ++i) {
            int newX = x + dx[i];
            int newY = y + dy[i];
            dfs(grid, newX, newY, count);
        }
    }
};

解法3:Union-Find

注意,并查集算法并不需要上下左右4个方向,只需要下和右两个方向就可以了。为什么呢?因为union算法决定了连在一起的都是一个连通块,所以不需要再往左和上再搞一次了。

而BFS和DFS则必须要上下左右4个方向处理。为什么呢?我们看下面的矩阵M:

[[1,1,0,0,0],
 [0,1,0,0,1],
 [0,0,2,1,2],
 [0,0,0,0,0],
 [0,0,0,0,2]]
M[1][4]=1,此时如果只往下和右方向走就只会处理M[2][4],而不会处理与之相连的M[2][2]和M[2][3]。

而并查集算法则会把M[1][4]和M[2][4]的祖先合成一个,到时候再处理M[2][2]和M[2][3]的时候又把其祖先合成一个,处理M[2][3]和M[2][4]的时候又把其祖先合成一个。这样,大家就都是一个连通块了。
注意,并查集并不需要把grid[][]元素改成0,而BFS/DFS可以这样做,从而省掉一个visited数组。

class Solution {
public:
    /**
     * @param grid: an integer matrix
     * @return: an integer 
     */
    int numIslandCities(vector<vector<int>> &grid) {
          int m = grid.size();
          int n = grid[0].size();
          father.resize(m * n);
          hasCity.resize(m * n);
          
          // initialize
          for (int i = 0; i < m; ++i) {
              for (int j = 0; j < n; ++j) {
                  father[i * n + j] = i * n + j;
                  hasCity[i * n + j] = grid[i][j] == 2 ? true : false;
                  if (grid[i][j] == 2) count++;
              }
          }
          
          //union-find
          for (int i = 0; i < m; ++i) {
              for (int j = 0; j < n; ++j) {
                  if (grid[i][j] != 0) {
                      if (i + 1 >= 0 && i + 1 < m && j >= 0 && j < n && grid[i + 1][j] != 0) {
                          add(i * n + j, (i + 1) * n + j);
                      }
                      
                       if (i >= 0 && i < m && j + 1 >= 0 && j + 1 < n && grid[i][j + 1] != 0) {
                          add(i * n + j, i * n + j + 1);
                      }
                  }
              }
          }
          
          return count;
    }
    
private:
    vector<int> father;
    vector<bool> hasCity;
    int count = 0;
    
    int find(int x) {
        if (father[x] == x) return x;
        father[x] = find(father[x]);
        return father[x];
    }
    
    void add(int a, int b) {
        int root_a = find(a);
        int root_b = find(b);
        if (root_a != root_b) {
            father[root_a] = root_b;
            if (hasCity[root_a] && hasCity[root_b]) count--;
            if (hasCity[a] || hasCity[b]) {
                hasCity[a] = hasCity[b] = true;
            }
        }
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值