ARTS_011

"week 11"

Posted by Xion on January 11, 2019      views:

这是耗子叔发起的一个活动,每周为一个周期,需要完成以下内容

  • Algrothm: leetcode算法题目
  • Review: 阅读并且点评一篇英文技术文章
  • Tip/Techni: 学习一个技术技巧
  • Share: 分享一篇有观点和思考的技术文章

[Algrothm] Friend Circles

question

547. Friend Circles
Medium

850

63

Favorite

Share
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:
N is in range [1,200].
M[i][i] = 1 for all students.
If M[i][j] = 1, then M[j][i] = 1.

思路

自己想到的思路主要是从数据结构上考虑的

思路1: 1 –> {1} 2 –> {2} 3 –> {3}

人指向盆友全,盆友圈也指向人,一旦发现有两个人是朋友,通知圈子中所有人更新

思路2: 构造一个这样的数据结构

circle{ people: {} belong_to: circle_id }

因为小圈子肯定属于大圈子

解法

屌丝方法,最快情况下复杂度达到o(n),n是len(M)

class Solution(object):
    def findCircleNum(self, M):
        """
        :type M: List[List[int]]
        :rtype: int
        """
        people_nums = len(M)
        people2zones = {i: {i} for i in range(people_nums)}
        zone2people = {(i,): [i, ] for i in range(people_nums)}

        for people in range(people_nums):
            for friend in range(people, people_nums):
                if M[people][friend] == 1:
                    this_circle = people2zones[people]
                    circle = people2zones[friend]
                    this_peoples = zone2people[tuple(this_circle)]
                    peoples = zone2people[tuple(circle)]
                    this_circle.update(circle)
                    new_circle = this_circle
                    for p in set(this_peoples + peoples):
                        people2zones[p] = new_circle
                        zone2people[tuple(new_circle)] = list(set(this_peoples + peoples))

        ret = len({id(v) for v in people2zones.values()})
        return ret
class Circle(object):
    def __init__(self,peoples):
        self.peoples = set(peoples)
        self.belong_to = None

    def __hash__(self):
        return hash(tuple(self.peoples))

    def __repr__(self):
        return str(tuple(self.peoples))

class Solution(object):


    def findCircleNum(self, M):
        people_nums = len(M)
        circles = [Circle([i,]) for i in range(people_nums)]
        circle_register = set(circles)

        for people in range(people_nums):
            for friend in range(people+1, people_nums):
                if M[people][friend] == 1:
                    this_circle = circles[people]
                    other_circle = circles[friend]
                    while True:
                        tmp = this_circle.belong_to
                        if not tmp:
                            break
                        this_circle = tmp
                    while True:
                        tmp = other_circle.belong_to
                        if not tmp:
                            break
                        other_circle = tmp
                    circle_register.discard(this_circle)
                    circle_register.discard(other_circle)
                    new_circle = Circle(this_circle.peoples.union(other_circle.peoples))
                    circle_register.add(new_circle)
                    this_circle.belong_to = new_circle
                    other_circle.belong_to = new_circle
        return len(circle_register)
      

solution

其实这里运用了一个union find的方法,以前没接触过 这里介绍了一下union find是怎么做的 https://www.youtube.com/watch?v=VJnUwsE4fWA

这里给自己暴露了一个问题,算法基础结构不知道,并查集。

[Review]

[Tip]

[Share]