作者: 负雪明烛
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. 基于MS SQL Server的数据库学习安排

    序号 分类 学习内容 目标/要求 方式 学时 考核 参考资料 1 基础知识 数据库理论 理解数据库基本理论 面授 1 能阐述元素.数据记录.数据表.数据库的基本概念T-SQL语法要求 https:// ...

  2. 微信小程序调试bug-日程计划类

    首先嘤嘤嘤一下,破bug,改了我一天,摔(′д` )-彡-彡 写的个微信小程序 逻辑如下,正常的功能是,我可以新建,修改,查询(按筛选条件),删除某个日程信息,后面贴个页面,我的bug出现就很搞笑了, ...

  3. SpringCloud微服务实战——搭建企业级开发框架(三十):整合EasyExcel实现数据表格导入导出功能

      批量上传数据导入.数据统计分析导出,已经基本是系统必不可缺的一项功能,这里从性能和易用性方面考虑,集成EasyExcel.EasyExcel是一个基于Java的简单.省内存的读写Excel的开源项 ...

  4. 学习java的第十四天

    一.今日收获 1.完成了手册第二章没有验证完成的例题 2.预习了第三章的算法以及for语句与if语句的用法 二.今日难题 1.验证上出现问题,没有那么仔细. 2.第二章还有没有完全理解的问题 三.明日 ...

  5. 巩固javaweb的第二十八天

    巩固内容: 设置页面的编码方式 实现代码: 每个 JSP 页面都需要设置编码方式,设置 JSP 页面的编码方式可以是下面两种方式 之一. 方式一: <%@ page contentType=&q ...

  6. 学习Java 2021/10/7

    java重写Override 重载Overload 重写是子类对父类的允许访问的方法的实现过程进行重新编写,返回值和形参都不能改变.即外壳不变,核心重写 重写规则: 参数列表与被重写方法的参数列表必须 ...

  7. 字节数与字符数mysql_mysql里一个中文汉字占多少字节数?

    在mysql中,如果是latin1字符集下,一个中文汉字占2个字节数:如果是utf8字符集下,一个中文汉字占3个字节数:如果是gbk字符集下,一个中文汉字占2个字节数. mysql各字符集下汉字和字母 ...

  8. android 下动态获取控件的id

    有时候我们需要动态的取得一个一个控件的id,然后进行操作,经过在网上查找,找到了一下方法getResources().getIdentifier("textView01", &qu ...

  9. HTML样式 背景

    当浏览器读到一个样式表,就会按照这个格式表来对文档进行格式化.有以下三种方式来插入样式表: 1.外部样式表 当样式需要用到很多页面的时候,外部样式是理想的选择.使用外部样式表,就可以听过更改一个文件来 ...

  10. Linux基础命令---uptime

    uptime uptime指令用来显示系统运行多长时间.有多少用户登录.系统负载情况. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora.SUSE.openSUSE. ...