参照leetcode 695题
给定一个二维数组,a[i][j] == 1 (无向图)即为顶点,该顶点的坐标为 (i,j)。注意这里给定的矩阵不是邻接矩阵,这个矩阵给出的信息是顶点的坐标位置。
在进行图的遍历时
1.若要直接使用该矩阵,则在遍历时,从一个顶点到下一个顶点的操作需要注意
2.可将该矩阵转换为邻接表,邻接表作为遍历时的数据结构我们比较熟悉。
下面介绍如何将这个矩阵转化为邻接表。
在C/C++中,二维数组实际上是两个一维数组拼接而成,矩阵中的每个点的坐标(r,c)(r为所在行号,c为所在列号)都可以转换为一维索引,设矩阵的行数为R,列数为C,则(x,y)对应的一维索引为 rC+c 。这里的 rC+c 即为每个点的通相。这里需要注意的是对于数学坐标系和这个矩阵的坐标系不要搞混。日常中的数学(x,y)坐标x代表横坐标,y代表纵坐标。而矩阵a[r][c]代表的是r行和c列,这x,y和r,c刚好是相反的,不要弄混了。对于之前使用比较多的是矩阵坐标系,推荐使用矩阵下的坐标系,因为查找元素更为方便。
同样一维索引也可以转换为二维坐标(c,r):( index% C, index / C)
找到顶点后,需要寻找边。
以(r,c)点为例,那么我们只需要遍历(r+1,c+0)(r-1,c+0)(r+0,c+1)(r+0,c-1)四个点,若某个点的值为1,则为这两个顶点之间存在一条边。
这里有个技巧:创建数组:dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}}
给出伪码
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}}
for(i 0:3)
next_r = r +dir[i][0];
next_c = c +dir[i][1];
grid[r][c];
下面看代码逻辑(需要一定的转换技巧)
map<int,vector<int> > mp; //int->序号,vector用来存储边
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//四联通
int maxAreaOfIsland(vector<vector<int> >& grid) {
R = grid.size(); //行数
C = grid[0].size(); //列数
int c;//行坐标
int r;//纵坐标
int nextr,nextc;
vector<int> e; //用来存储边
for(int i = 0; i < C*R; i++){
//i从0~R*C-1,i即一维索引,只需在矩阵中挑出grid[c][r]为1的顶点
c = i % C;//计算该点的列号
r = i / C;//计算列号
if(grid[r][c] == 1){//找到顶点
for(int j = 0; j < 4; j++){//通过四联通寻找边
//循环四次,寻找四个方位的点
nextr = r+dir[j][0];
nextc = c+dir[j][1];
if(is(nextr,nextc) && grid[nextr][nextc] == 1){
//判断该点的四个方位是否有顶点,若存在点,
//则该顶点到那个方位存在一条边
e.push_back(mta(nextr,nextc));//存储边
}
}
//将所有的边都存储到mp中,并清空e,为下次存储边做准备
mp[mta(r,c)] = e;
e.clear();
}
}