作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/friend-circles/#/description

题目描述

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.

题目大意

有一些学生,他们的朋友关系是以邻接矩阵的形式给出的,并且朋友关系可以传递。求总共有多少个朋友圈子。

解题方法

经典的并查集问题,并查集就是考察一个组中的互相联通问题。在这个题中,就是看有几个好友环。

首先,定义一个200大小的数组,记录节点对应的根节点编号。findRoot(int x)函数是找出x节点的根节点,在查找某个特定节点的根节点时,同时将其与根节点之间的所有节点都指向根节点,这个工程叫做路径压缩。

在遍历矩阵之前,首先把数组所有的值都初始化为-1,这样如果之后某个节点的根节点编号为-1,说明它是根节点;如果某节点对应的根节点编号不是-1,那么说明这个节点不是根节点,并且已经被捆绑到另外的节点上。

遍历矩阵时,如果矩阵(i,j)位置的值为1,说明它们直接相连,分别用findRoot()找出i,j对应的根节点,如果根节点不相同,则把他们绑在一起。

最终统计下-1的个数,就是有多少个根节点,即有多少个环。

Java解法如下:

public class Solution {
int tree[] = new int[200];
public int findCircleNum(int[][] M) {
int len = M[0].length;
for(int i = 0; i < len; i++){
tree[i] = -1;
}
for(int i = 0; i < len; i++){
for(int j = 0; j < len; j++){
if(M[i][j] == 1){
int aRoot = findRoot(i);
int bRoot = findRoot(j);
if(aRoot != bRoot){
tree[aRoot] = bRoot;
}
}
}
}
int ans = 0;
for(int i = 0; i < len; i++){
if(tree[i] == -1){
ans++;
}
}
return ans;
} public int findRoot(int x){
if(tree[x] == -1){
return x;
}else{
int temp = findRoot(tree[x]);
tree[x] = temp;
return temp;
}
}
}

Python版本的解法使用了带权并查集,每次把权重小的加到权重大的上面,这样可以使树的高度尽可能低。权重表示树的节点个数。

代码如下:

class Solution(object):
def findCircleNum(self, M):
"""
:type M: List[List[int]]
:rtype: int
"""
dsu = DSU()
N = len(M)
for i in range(N):
for j in range(i, N):
if M[i][j]:
dsu.u(i, j)
res = 0
for i in range(N):
if dsu.f(i) == i:
res += 1
return res class DSU(object):
def __init__(self):
self.d = range(201)
self.r = [0] * 201 def f(self, a):
return a if a == self.d[a] else self.f(self.d[a]) def u(self, a, b):
pa = self.f(a)
pb = self.f(b)
if (pa == pb):
return
if self.r[pa] < self.r[pb]:
self.d[pa] = pb
self.r[pb] += self.r[pa]
else:
self.d[pb] = pa
self.r[pa] += self.r[pb]

在union方法中注意,需要把父亲节点进行union,而不是直接把a, b进行合并。

C++版本如下:


class Solution {
public:
int findCircleNum(vector<vector<int>>& M) {
const int N = M.size();
for (int i = 0; i < N; i ++)
map_.push_back(i);
for (int i = 0; i < N; i ++) {
for (int j = i + 1; j < N; j ++) {
if (M[i][j])
u(i, j);
}
}
int res = 0;
for (int i = 0; i < N; i++) {
if (map_[i] == i)
res ++;
}
return res;
}
private:
vector<int> map_; //i的parent,默认是i
int f(int a) {
if (map_[a] == a)
return a;
return f(map_[a]);
}
void u(int a, int b) {
int pa = f(a);
int pb = f(b);
if (pa == pb)
return;
map_[pa] = pb;
}
};

日期

2017 年 4 月 20 日
2018 年 12 月 14 日 —— 12月过半,2019就要开始

【LeetCode】547. Friend Circles 解题报告(Python & Java & C++)的更多相关文章

  1. LeetCode 547. Friend Circles 朋友圈(C++/Java)

    题目: https://leetcode.com/problems/friend-circles/ There are N students in a class. Some of them are ...

  2. 【LeetCode】120. Triangle 解题报告(Python)

    [LeetCode]120. Triangle 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址htt ...

  3. 【剑指Offer】不用加减乘除做加法 解题报告(Java)

    [剑指Offer]不用加减乘除做加法 解题报告(Java) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews 题 ...

  4. LeetCode 1 Two Sum 解题报告

    LeetCode 1 Two Sum 解题报告 偶然间听见leetcode这个平台,这里面题量也不是很多200多题,打算平时有空在研究生期间就刷完,跟跟多的练习算法的人进行交流思想,一定的ACM算法积 ...

  5. 【LeetCode】Permutations II 解题报告

    [题目] Given a collection of numbers that might contain duplicates, return all possible unique permuta ...

  6. 【LeetCode】Island Perimeter 解题报告

    [LeetCode]Island Perimeter 解题报告 [LeetCode] https://leetcode.com/problems/island-perimeter/ Total Acc ...

  7. 【LeetCode】01 Matrix 解题报告

    [LeetCode]01 Matrix 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/01-matrix/#/descripti ...

  8. 【LeetCode】Largest Number 解题报告

    [LeetCode]Largest Number 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/largest-number/# ...

  9. 【LeetCode】Gas Station 解题报告

    [LeetCode]Gas Station 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/gas-station/#/descr ...

随机推荐

  1. R语言与医学统计图形【1】par函数

    张铁军,陈兴栋等 著 R语言基础绘图系统 基础绘图包之高级绘图函数--par函数 基础绘图包并非指单独某个包,而是由几个R包联合起来的一个联盟,比如graphics.grDevices等. 掌握par ...

  2. R语言与医学统计图形-【18】ggplot2几何对象汇总

    ggplot2绘图系统--几何对象汇总 前面介绍了常见的几种基本的几何对象,并且介绍了scale.stat等其他要素.后续将介绍position.themes.coord和faceting等函数. 这 ...

  3. C语言 文本字符串存入二维数组

    字符串存入数组 文本内容: line1_1 line1_2line2_1 line2_2line3_1 line3_2line4_1 line4_2line5_1 line5_2line6_1 lin ...

  4. Mysql-单个left join 计算逻辑(一对多问题)

    BUG背景: 我们有一个订单表 和 一个 物流表 它们通过 订单ID 进行一对一的关系绑定.但是由于物流表在保存订单信息的时候没有做判断该订单是否已经有物流信息,这就变成同一个订单id在物流表中存在多 ...

  5. 数仓:解读 NameNode 的 edits 和 fsimage 文件内容

    一.edits 文件 一)文件组成 一个edits文件记录了一次写文件的过程,该过程被分解成多个部分进行记录:(每条记录在hdfs中有一个编号) 每一个部分为: '<RECORD>...& ...

  6. CR LF 的含义

    可以参考: 转载于:https://www.cnblogs.com/babykick/archive/2011/03/25/1995977.html

  7. linux 挂载本地iso

    mount -t iso9660 -o loop /mnt/temp/rhel-server-6.5-i386-dvd.iso /mnt/cdrom -t :设备类型 iso9660是指CD-ROM光 ...

  8. Linux基础命令---enable开启shell命令

    enable enable指令用来关闭或者激活shell内部命令.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora. 1.语法       enable [-a]   ...

  9. 【AWS】【TroubleShooting】EC2实例无法使用SSH远程登陆(EC2 failure for SSH connection)

    1. Login AWS web console and check the EC2 instance.

  10. Linux学习 - 文件系统常用命令

    一.文件系统查看命令df df [选项] [挂载点] -a 查看所有文件系统信息,包括特殊文件系统 -h 使用习惯单位显示容量 -T 显示文件系统类型 -m 以MB为单位显示容量 -k 以KB为单位显 ...