Given matrix MxN of 0s and 1s, return and output all groups of adjacent 1s in form of (row,col)...
1s are considered adjacent if they are adjacent horizontally or vertically.
1 1 0 1 0 1
1 1 1 1 0 1
0 0 0 0 1 1
1 0 1 0 1 0
Output:
A: (0,0)(1,0)(0,1)(1,1)(1,2)(1,3)(0,3)
B: (0,5)(1,5)(2,4)(2,5)(3,4)
C: (3,0)
D: (3,2)
Order in the output is insignificant.
#include <iostream>
#include <vector>
#include <functional>
#include <unordered_map>
using namespace std;
// solution with changing the original matrix
vector<vector<pair<int,int>>> findIslands(vector<vector<int>>& mat) {
int m = mat.size(), n = mat[0].size();
vector<vector<pair<int,int>>> res;
vector<pair<int,int>> list;
vector<vector<int>> dirs = {{0,1},{0,-1},{1,0},{-1,0}};
function<void(int,int)> dfs = [&](int r, int c) {
list.emplace_back(r,c);
mat[r][c] = 0;
for(auto& dir:dirs) {
int i = r+dir[0], j = c+dir[1];
if(i<0 || j<0 || i>=m || j>=n || !mat[i][j]) continue;
dfs(i, j);
}
};
for(int i=0; i<m; i++) {
for(int j=0; j<n; j++) {
if(mat[i][j]) {
list.clear();
dfs(i, j);
res.push_back(list);
}
}
}
return res;
}
// solution without changing the original matrix, using additional visited bool matrix
vector<vector<pair<int,int>>> findIslands1(vector<vector<int>>& mat) {
int m = mat.size(), n = mat[0].size();
vector<vector<pair<int,int>>> res;
vector<pair<int,int>> list;
vector<vector<bool>> visited(m, vector<bool>(n));
vector<vector<int>> dirs = {{0,1},{0,-1},{1,0},{-1,0}};
function<void(int,int)> dfs = [&](int r, int c) {
list.emplace_back(r,c);
visited[r][c] = true;
for(auto& dir:dirs) {
int i = r+dir[0], j = c+dir[1];
if(i<0 || j<0 || i>=m || j>=n || !mat[i][j] || visited[i][j]) continue;
dfs(i, j);
}
};
for(int i=0; i<m; i++) {
for(int j=0; j<n; j++) {
if(mat[i][j] && !visited[i][j]) {
list.clear();
dfs(i, j);
res.push_back(list);
}
}
}
return res;
}
// solution without changing the original matrix and without additional memory space
vector<unordered_map<int,vector<pair<int,int>>>> findIslands2(vector<vector<int>>& mat) {
int m = mat.size(), n = mat[0].size();
vector<unordered_map<int,vector<pair<int,int>>>> res;
unordered_map<int,vector<pair<int,int>>> map;
vector<vector<int>> dirs = {{0,1},{0,-1},{1,0},{-1,0}};
auto exists = [&](int r, int c) {
for(auto& mp:res) {
if(mp.count(r)) {
for(auto& p:mp[r])
if(p.first <= c && p.second >= c)
return true;
}
}
return false;
};
function<void(int,int)> dfs = [&](int r, int c) {
if(map.count(r)) {
bool inserted = false;
for(auto& p:map[r]) {
if(p.first <= c && p.second >= c) return;
if(c+1 == p.first) {
p.first = c;
inserted = true;
break;
} else if(c-1 == p.second) {
p.second = c;
inserted = true;
break;
}
}
if(!inserted)
map[r].push_back({c, c});
} else {
map[r].push_back({c, c});
}
for(auto& dir:dirs) {
int i = r+dir[0], j = c+dir[1];
if(i<0 || j<0 || i>=m || j>=n || !mat[i][j]) continue;
dfs(i, j);
}
};
for(int i=0; i<m; i++) {
for(int j=0; j<n; j++) {
if(mat[i][j] && !exists(i,j)) {
map.clear();
dfs(i, j);
res.push_back(map);
}
}
}
return res;
}
int main() {
vector<vector<int>> mat = { {1, 1, 0, 1, 0, 1},
{1, 1, 1, 1, 0, 1},
{0, 0, 0, 0, 1, 1},
{1, 0, 1, 0, 1, 0}};
auto res1 = findIslands1(mat);
for(auto& list:res1) {
for(auto& p:list)
cout << "(" << p.first << "," << p.second << ") ";
cout << endl;
}
auto res2 = findIslands2(mat);
for(auto& map:res2) {
for(auto& kv:map)
for(auto& pair:kv.second)
for(int i=pair.first; i<=pair.second; i++)
cout << "(" << kv.first << "," << i << ") ";
cout << endl;
}
return 0;
}