问题来源

此题来源于LeetCode547. Friend Circles,主要运用了并查集(union find)、广度优先遍历(bfs)和深度优先遍历(bfs)三种方法解决。

问题简述

给定一个N×NN \times N的矩阵MM表示了NN个人之见的朋友关系。如果M[i][j]=1M[i][j]=1那么ii和jj是直接朋友关系;如果M[i][j]=1M[i][j]=1,M[j][k]=1M[j][k]=1,M[i][k]=0M[i][k]=0,那么ii和kk是间接朋友关系。我们假定有直接和间接朋友关系的人为一个朋友圈,试问MM中有几个朋友圈。
比如:

输入:
[[1,1,0],[1,1,0],[0,0,1]]
输出: 2
解释:第0和第1个人是直接朋友,他们构成1个朋友圈;第2个人自己构成一个朋友圈,所以返回2。

又比如:

输入:
[[1,1,0],[1,1,1],[0,1,1]]
输出: 1
解释:第0和第1个人是直接朋友,第1和第2个人是直接朋友,所以第0和第2个人是间接朋友,这3个人构成了1个朋友圈,所以返回1。 

值得注意的是:

  • 总是有M[i][j]=M[j][i]M[i][j]=M[j][i]

    • 总是有M[i][i]=1M[i][i]=1
    • 解决方案

      利用union find解决

      此处的并查集用到了路径压缩的优化。

      class Solution {
      private:vector<int> vec;int sz;private:void Initialize(int count){vec = vector<int>(count);sz = count;for (int i = 0; i < count; i++)vec[i] = i;}int findRoot(int p){assert(p >= 0 && p < sz);while (vec[p] != p){//路径压缩vec[p] = vec[vec[p]];p = vec[p];}return vec[p];}void unionNode(int p, int q){assert(p >= 0 && p < sz && q >= 0 && q < sz);int pRoot = findRoot(p);int qRoot = findRoot(q);if (pRoot != qRoot)vec[pRoot] = qRoot;}public:int findCircleNum(vector<vector<int>>& M) {int m = M.size();if (0 >= m)return 0;Initialize(m);for (int i = 0; i < m; i++){for (int j = i + 1 ; j < m; j++){if (M[i][j] == 1)unionNode(i, j);}}int res = 0;for (int i = 0; i < m; i++)if (vec[i] == i)res++;return res;}
      };

      利用bfs解决

      由于问题的特殊性,每次都只要把对角线上的元素放到队列当中即可。

      class Solution {
      private:int sz;private:void bfs(vector<vector<int>> &M, int x){queue<int> q;q.push(x);while(!q.empty()){int newX = q.front();q.pop();M[newX][newX] = 0;for (int i = 0; i < sz; i++){if (1 == M[newX][i]){M[newX][i] = 0;M[i][newX] = 0;if (1 == M[i][i])q.push(i);}}}return;}public:int findCircleNum(vector<vector<int>>& M) {int m = M.size();if (0 >= m)return 0;sz = m;int res = 0;for (int i = 0; i < m; i++){if (1 == M[i][i]){bfs(M,i);res++;}}       return res;}
      };

      利用dfs解决

      dfs与bfs的思路大同小异,但元素过多可能会造成栈溢出。

      class Solution {
      private:int sz;private:void dfs(vector<vector<int>> &M, int x, int y){if (0 == M[x][y])return;M[x][y] = 0;for (int i = 0; i < sz; i++){if (1 == M[x][i]){M[x][i] = 0;M[i][x] = 0;dfs(M, i, i);}}return;}public:int findCircleNum(vector<vector<int>>& M) {int m = M.size();if (0 >= m)return 0;sz = m;int res = 0;for (int i = 0; i < m; i++){if (1 == M[i][i]){dfs(M,i,i);res++;}}  return res;}
      };

      结束语

      以上三种方法最快的是并查集(union find),bfs和dfs的速度差不多,三者也许都还有优化的余地~

LeetCode547. Friends Circles 利用union find | bfs | dfs三种方法解决相关推荐

  1. java利用实现大数阶乘(三种方法)

    java利用实现大数阶乘(三种方法) 法一: for循环 import java.math.BigInteger; import java.util.Scanner; public class das ...

  2. 利用yum下载软件包的三种方法

    方法一:downloadonly插件 1.安装插件 yum -y install yum-download 2.下载httpd软件包到当前文件夹内 yum -y install httpd -down ...

  3. 广度优先搜索(BFS)最短路径输出表示(三种方法)

    相信我,看完之后,你会对BFS有种全新的了解,彻底掌握BFS 只需要这一篇就足够啦,狗头 BFS路径表示 广度优先搜索顾名思义就是以迷宫里的无向图某一个点,借助队列,一层一层以该点为中心散开进行搜索, ...

  4. java list 删除 遍历_Java list利用遍历进行删除操作3种方法解析

    Java list利用遍历进行删除操作3种方法解析 这篇文章主要介绍了Java list利用遍历进行删除操作3种方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需 ...

  5. 利用IP查主机名的三种方法

    利用IP查主机名的三种方法 在局域网内,我们常使用一些工具来查IP查主机名, 利用ipconfig或者ping可以查到IP地址,也是我们常使用的工具.而要查网内的主机,可以用网上邻居,其实 我们也有一 ...

  6. 网上赚钱的门路方法,大部分人都是利用这三种方法!

    想通过网络来挣钱,无外乎以下方法:用时间来赚钱.用钱来生钱.通过推广赚钱.而每一种挣钱方式,都是需要有一定付出的,只有付出了才会有收获.本文就来给大家介绍一下想要通过网赚挣钱,我们都应该了解些什么?网 ...

  7. TCGA数据库的利用(三)—做差异分析的三种方法

    今天更新TCGA数据库的利用系列第三篇文章,在对TCGA数据进行挖掘时,通常会筛选出来一些表达量显著异常的基因,作为后续研究的对象,这个筛选过程叫做差异分析:本篇文章将分为三大模块对差异分析进行介绍 ...

  8. java 遍历删除list_Java list利用遍历进行删除操作3种方法解析

    这篇文章主要介绍了Java list利用遍历进行删除操作3种方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Java三种遍历如何进行list ...

  9. 利用opencv实现图像马赛克处理的三种方法

    前言:本文就图像的马赛克处理,基于opencv提出了三种解决方案,并详细地介绍了三种方法的原理.示例.问题及问题的解决方案. 方法一 原理介绍:利用resize()将图片先缩小,再放大 代码示例: i ...

最新文章

  1. Python 的一万种用法:制作 Web 可视化页面
  2. iOS应用性能调优的25个建议和技巧【转】
  3. BZOJ.2707.[SDOI2012]走迷宫(期望 Tarjan 高斯消元)
  4. Learning ROS: Service and Client (C++)
  5. 你不知道LinkedList中的方法
  6. LNK2019 无法解析的外部符号 __imp_CommandLineToArgvW,该符号在函数 WinMain 中被引用
  7. 下一代微服务Service Mesh原理及实践
  8. abap java_ABAP,Java和JavaScript的序列化,反序列化
  9. (1)c语言学习总结之从关键字到循环结构
  10. c语言程序设计及gis,C语言程序设计(西安工程大学)2020知到答案全套
  11. hive 如何将数组转成字符串_Hive 字符串操作[转]
  12. Android 查看是否支持指定解码器(H265)
  13. 南宁Java程序员平均工资_南宁程序员平均工资 在南宁做程序员有一万工资吗
  14. 移动路由器刷linux,家用WIFI路由器硬改刷系统(DIY智能路由器)
  15. php 发邮件 上传附件,PHPMailer实现PHP的邮件发送,附带附件
  16. linux中安装apr
  17. ns注册改服务器,NameSilo域名更改NS服务器简单过程介绍
  18. 银河麒麟用QIFW制作安装包
  19. PHP解决中文乱码问题
  20. esp32 smtp发送邮件micropython

热门文章

  1. 解决AttributeError AttributeError: 'NoneType' object has no attribute 'filename'
  2. WSGI直观形象的了解一下
  3. 在启动HDFS时,针对集群中namenode无法识别datanode的问题的解决方法
  4. C# 线程池ThreadPool
  5. C++成员函数重载、覆盖和隐藏的区别
  6. 基于matlab 宗晓萍,基于ADAMS和MATLAB的机械臂控制仿真
  7. 驱动框架8——将驱动集成到内核中
  8. Netty源码学习(零)前言
  9. angularjs控制器之间的数据共享与通信
  10. [Leetcode]@python 107. Binary Tree Level Order Traversal II