827. Making A Large Island

827. Making A Large Island


There are N students in a class. Some of them are friends, while some are not. Their friendship is transitive in nature. For example, if A is a direct friend of B, and B is a direct friend of C, then A is an indirect friend of C. And we defined a friend circle is a group of students who are direct or indirect friends.

Given a N*N matrix M representing the friend relationship between students in the class. If M[i][j] = 1, then the ith and jth students are direct friends with each other, otherwise not. And you have to output the total number of friend circles among all the students.

Example 1:

Input: 
[[1,1,0],
 [1,1,0],
 [0,0,1]]
Output: 2
Explanation:The 0th and 1st students are direct friends, so they are in a friend circle. 
The 2nd student himself is in a friend circle. So return 2.

Example 2:

Input: 
[[1,1,0],
 [1,1,1],
 [0,1,1]]
Output: 1
Explanation:The 0th and 1st students are direct friends, the 1st and 2nd students are direct friends, 

so the 0th and 2nd students are indirect friends. All of them are in the same friend circle, so return 1.

Note:

  1. N is in range [1,200].
  2. M[i][i] = 1 for all students.
  3. If M[i][j] = 1, then M[j][i] = 1.

方法1: dfs

xiaocong1990: https://blog.csdn.net/xiaocong1990/article/details/80627946

思路:

将这个问题拆分成几个子问题:

1.第一次dfs遍历,从所有的1入手,找到图中有多少个connected component,每一个component的面积是多少。这个信息我们用一个hashmap来记录,{id: area}。id 取0, 1 以外的数字,也就是从2开始,那么就可以代替visited这个矩阵,来辨认是否被遍历过。
2. 第二次遍历,从所有的0入手,检查它相邻的四个格子是否被标记了id,如果标记了,hash一下,并将这个cc所对应的面积加进来。记录一个全球最大值。

用到的数据结构:
unordered_map<int, int> concomp: 第一次遍历中记录{id: area}
unordered_set hash:在第二次遍历中记录每个0上下左右被相连的component id。

易错点

  1. 不要忘了加自己
  2. 上面第二个hash容易遗漏

Complexity

Time complexity: O(nm)
Space complexity: O(n
m)

class Solution {
public:
    int largestIsland(vector<vector<int>>& grid) {
        if (grid.empty() || grid[0].empty()) return 0;
        unordered_map<int, int> concomp;
        
        int id = 2;
        for (int i = 0; i < grid.size(); i++) {
            for (int j = 0; j < grid[0].size(); j ++) {
                if (grid[i][j] == 1) {
                     int area = dfs(grid, i, j, id, 1);
                     concomp[id] = area;
                     id++;
                }
            }
        }
        
        int result = 0;
        
        for (int i = 0; i < grid.size(); i++) {
            for (int j = 0; j < grid[0].size(); j ++) {
                if (grid[i][j] == 0) {
                    int area = 1;
                    unordered_set<int> hash = {(i > 0 ? grid[i - 1][j] : 0),
                                              (i < grid.size() - 1 ? grid[i + 1][j] : 0),
                                              (j > 0 ? grid[i][j - 1] : 0),
                                              (j < grid[0].size() - 1 ? grid[i][j + 1]: 0)};
                    
                    for (auto item: hash) {
                        area += concomp[item];
                    }
                    
                    result = max(result, area);
                }
                
            }
        }
        
        if (!result) return concomp.size() ? grid.size() * grid[0].size() : 0;
        return  result;
    }
    
    int dfs(vector<vector<int>> & grid, int i, int j, int id, int area) {
        if (i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() || grid[i][j] != 1) return 0;;
        
        grid[i][j] = id;
       
        return 1 
            + dfs(grid, i + 1, j, id, area) 
            + dfs(grid, i - 1, j, id, area)
            + dfs(grid, i, j - 1, id, area)
            + dfs(grid, i, j + 1, id, area);
    }
};

huahua: http://zxi.mytechroad.com/blog/graph/leetcode-827-making-a-large-island/
封装的更整洁的写法。

 // Author: Huahua
// Running time: 14 ms
class Solution {
public:
  int largestIsland(vector<vector<int>>& grid) {
    color_ = 1;
    g_ = &grid;
    m_ = grid.size();
    n_ = grid[0].size();
    unordered_map<int, int> areas; // color -> area
    int ans = 0;
    for (int i = 0; i < m_; ++i)
      for (int j = 0; j < n_; ++j)
        if (grid[i][j] == 1) {
          ++color_;
          areas[color_] = getArea(j, i);
          ans = max(ans, areas[color_]);
        }
    for (int i = 0; i < m_; ++i)
      for (int j = 0; j < n_; ++j)
        if (grid[i][j] == 0) {                    
          int area = 1;
          for (int color : set<int>{getColor(j, i - 1), getColor(j, i + 1),
                                    getColor(j - 1, i), getColor(j + 1, i)}) 
            area += areas[color];
          ans = max(ans, area);
        }
    return ans;
  }
private:
  int m_;
  int n_;
  int color_;
  vector<vector<int>>* g_; // does not own the object.
  
  int getColor(int x, int y) {
    return (x < 0 || x >= n_ || y < 0 || y >= m_) ? 0 : (*g_)[y][x];
  }
  
  // Return the area of a connected component, set all elements to color_.
  int getArea(int x, int y) {
    if (x < 0 || x >= n_ || y < 0 || y >= m_ || (*g_)[y][x] != 1) return 0;
    (*g_)[y][x] = color_;
    return 1 + getArea(x - 1, y) + getArea(x + 1, y) 
             + getArea(x, y - 1) + getArea(x, y + 1);
  }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值