朋友圈数量
题目:
给一个矩阵,里面记录着每个人同其他人是否是朋友关系,并且朋友关系具备可传递性。
题目连接:https://leetcode-cn.com/problems/friend-circles/?tdsourcetag=s_pctim_aiomsg
题目分析:
这个题说到底还是自己对递归理解的不深刻,同时为了强行套用以往的深搜的公式。应该以每个人为中心,对他以及认识的朋友进行搜索。以下图为例进行搜索过程的解析。
A的朋友是B,然后以B为中心对B展开搜索,B的朋友有C和D,分别以C和D为中心对C和D进行搜索,C没有朋友搜索结束,而D的朋友是E,继续以E为中心对E展开搜索。
与下面的岛屿面积一题相比,这一题解策略的构造是搜索整个节点空间,如果符合副中心点条件,再进行递归搜索。所以这一题的解策略是
for(int j = 0;j < M.length;j++)
而岛屿一题的解策略的构造是(-1,0),(1,0),(0,-1),(0,1)这四种策略。这也是两种典型的题目的区别,即一种是显式的矩形图的搜索,而另一种则是其他线性图或者树之类的结构。但是只要认真思考
其中递归策略以及解策略的构造即可把握题目的脉络。
代码如下:
class Solution {
private void dfs(int[][] M,boolean[] visited,int i){
for(int j = 0;j < M.length;j++){
if(M[i][j] == 1 && !visited[j]){
visited[j] = true;
dfs(M,visited,j);
}
}
}
public int findCircleNum(int[][] M) {
int result = 0;
boolean[] visited = new boolean[M.length];
// visiited代表的含义是每个人是否被访问过,因为这个是无向图,所以不需要存储互相的访问状态
for(int i = 0;i < M.length;i++){
if(!visited[i]){
dfs(M,visited,i);
result++;
}
}
return result;
}
}

这个题与LC中的第200题非常相似。
LC200 题目:
找出地图中岛屿的个数。
分析:遍历地图中的每一个角度,如果是陆地(‘1’),那么就以此点为中心往([x-1,y],[x+1,y],[x,y-1],[x,y+1])四个方向进行搜索。
以[x-1,y]方向为例,在[x-1,y]方向找到为‘1’的点后以[x-1,y]为中心往[x-1,y]的四个方向进行搜索,直到某一点不为‘1’,此过程为递归过程。
code:
1 class Solution {
2 public void dfs(char[][] grid,int i,int j){
3 if (i > grid.length || j > grid[0].length){
4 return;
5 }
6 grid[i][j] = '0';
7 if ((i-1) >= 0 && grid[i-1][j] == '1'){
8 dfs(grid,i-1,j);
9 }
10
11 if ((i+1) < grid.length && grid[i+1][j] == '1'){
12 dfs(grid,i+1,j);
13 }
14
15 if (j-1 >= 0 && grid[i][j-1] == '1'){
16 dfs(grid,i,j-1);
17 }
18
19 if ((j+1) < grid[0].length && grid[i][j+1] == '1'){
20 dfs(grid,i,j+1);
21 }
22 }
23 public int numIslands(char[][] grid) {
24 if(grid.length == 0 || grid == null){
25 return 0;
26 }
27 int result = 0;
28 //boolean[][] visited = new boolean[grid.length][grid[0].length];
29 for (int i = 0;i < grid.length;i++){
30 for (int j = 0;j < grid[0].length;j++){
31 if (grid[i][j] == '1'){
32 dfs(grid,i,j);
33 result++;
34 }
35 }
36 }
37
38 return result;
39 }
40 }
与上题的对比:
两者的搜索的方向并不相同。第一题是以某个人为中心后,将所有人重新扫描一边,如果找到朋友了,以该朋友为副中心继续扫描。
也就是说找到中心点后,搜索方向也就是所有人都会是递归的起点,所以第一题在for循环中调用了递归。
反观第二题,找到中心点之后,只需要从上下左右四个方向进行搜索,也就是说递归方向只有4个。
搜索的方向/范围,也就是递归开始的起点,搜索也就是寻找下一个中心点,而这个过程是个递归的过程。
浙公网安备 33010602011771号