题目要求

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 ithand jthstudents 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. Mi = 1 for all students.
  3. If Mi = 1, then Mj = 1.

思路一:深度优先遍历

每当遇到一个还没有加入任何朋友圈的人(即Mi=1),就开始遍历其还未加入任何朋友圈的朋友,并再访问这些朋友的朋友,将其加入改人所在的朋友圈(使Mj=0, Mi=0),直到M中所有的值都为0,说明找到了所有的朋友圈。

public int findCircleNum(int[][] M) {  
    int numOfFriends = M.length;  
    int count = 0;  
    for (int i = 0 ; i<numOfFriends ; i++) {  
        if (M[i][i] == 1) {  
            count++;  
            traverseFriendCircle(M, i, i);  
        }  
    }  
    return count;  
}  
  
public void traverseFriendCircle(int[][] M, int friendIndex, int fromFriendIndex) {  
    M[fromFriendIndex][friendIndex] = 0;  
    M[friendIndex][fromFriendIndex] = 0;  
    M[friendIndex][friendIndex] = 0;  
    for (int i = 0 ; i<M.length ; i++) {  
        if (M[friendIndex][i] == 1) {  
            traverseFriendCircle(M, i, friendIndex);  
        }  
    }  
}

思路二:Union Find

这题就是标准的Union Find的题目,通过找到所有有关联的节点,将其加入到一个关联树中,利用标准的Union Find的union和find操作即可找到所有的关联树。

private int[] parentRoot;  
private int[] ranks;  
  
private int findParent(int i) {  
    while (i != parentRoot[i]) {  
        parentRoot[i] = parentRoot[parentRoot[i]];  
        i = parentRoot[i];  
    }  
    return i;  
}  
  
private void union(int i, int j) {  
    int parentOfI = findParent(i);  
    int parentOfJ = findParent(j);  
    if (parentOfI == parentOfJ) {return;}  
    if (ranks[parentOfI] > ranks[parentOfJ]) {  
        parentRoot[parentOfJ] = parentOfI;  
        ranks[parentOfI]++;  
    } else {  
        parentRoot[parentOfI] = parentOfJ;  
        ranks[parentOfJ]++;  
    }  
}  
  
public int findCircleNum2(int[][] M) {  
    int numOfFriends = M.length;  
    parentRoot = new int[numOfFriends];  
    ranks = new int[numOfFriends];  
    for (int i = 0 ; i < numOfFriends ; i++) {  
        parentRoot[i] = i;  
    }  
    for (int i = 0 ; i<numOfFriends ; i++) {  
        for (int j = i+1 ; j<numOfFriends ; j++){  
            if (M[i][j] == 1) {  
                union(i, j);  
            }  
        }  
    }  
    int count = 0;  
    for (int i = 0 ; i<numOfFriends ; i++) {  
        if (parentRoot[i] == i) {  
            count++;  
        }  
    }  
    return count;  
}

raledong
2.7k 声望2k 粉丝

心怀远方,负重前行