1. 程式人生 > >[LeetCode] 547. Friend Circles

[LeetCode] 547. Friend Circles

題目

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. 初始化,unionFind_s 為 每個數對於的 集合號。 2. find函式 ,找出對應的數的 集合號。 3. merge 函式,將兩個元素對應的集合合併為一個。 4. 檢視集合的種類。

在本題中,朋友關係矩陣由於是對稱的所以,只用遍歷 除去對角的 上三角。當矩陣[i,j]為”1”,將i,j元素對應的集合合併。然後檢視共有多少種集合。

code

def findOp(unionFind_s,x):
    r = x
    while unionFind_s[r]!= r :
        r = unionFind_s[r]
    i = x
    while unionFind_s[i]!= r:
        t = unionFind_s[i]
        unionFind_s[i] = r 
        i = t
    return r

def UnionByHeightOp(unionFind_s,Height,a,b):
    a = findOp(unionFind_s,a)
    b = findOp(unionFind_s,b)
    if a == b:
        return 

    if Height[a] < Height[b]:
        unionFind_s[a] = b 
    elif Height[a] > Height[b]:
        unionFind_s[b] = a 
    else:
        unionFind_s[b] = a 
        Height[a] += 1



class Solution:
    def findCircleNum(self, M):
        """
        :type M: List[List[int]]
        :rtype: int
        """
        Mlen = len(M)
        unionFind_s = [i for i in range(Mlen)]
        Height = [0] * Mlen

        for i in range(Mlen):
            for j in range(i+1,Mlen):
                if M[i][j] == 1:
                    UnionByHeightOp(unionFind_s,Height,i,j)
        count = 0    
        for i in range(Mlen):
            if unionFind_s[i] == i:
                count += 1
        return count