日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

并查集c++代码_[Leetcode 每日精选](本周主题-并查集) 547. 朋友圈

發布時間:2023/11/27 生活经验 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并查集c++代码_[Leetcode 每日精选](本周主题-并查集) 547. 朋友圈 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目難度: 中等
原題鏈接
今天繼續來做并查集的問題, 這道題仍然比較基礎, 而且也是個比較接近現實的問題了. 大家在我的公眾號"每日精選算法題"中的聊天框中回復 并查集 就能看到該系列當前已經更新的文章了
大家有什么想法建議和反饋的話歡迎隨時交流, 包括但不限于公眾號聊天框/知乎私信評論等等~

題目描述

班上有 N 名學生。其中有些人是朋友,有些則不是。他們的友誼具有是傳遞性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我們可以認為 A 也是 C 的朋友。所謂的朋友圈,是指所有朋友的集合。

給定一個 N * N 的矩陣 M,表示班級中學生之間的朋友關系。如果 M[i][j] = 1,表示已知第 i 個和 j 個學生互為朋友關系,否則為不知道。你必須輸出所有學生中的已知的朋友圈總數。

  • N 在[1,200]的范圍內。
  • 對于所有學生,有 M[i][i] = 1。
  • 如果有 M[i][j] = 1,則有 M[j][i] = 1。

題目樣例

示例 1

輸入

[[1,1,0], [1,1,0], [0,0,1]]

輸出

2

解釋

  • 已知學生 0 和學生 1 互為朋友,他們在一個朋友圈。
  • 第 2 個學生自己在一個朋友圈。所以返回 2。

示例 2

輸入

[[1,1,0], [1,1,1], [0,1,1]]

輸出

1

解釋

已知學生 0 和學生 1 互為朋友,學生 1 和學生 2 互為朋友,所以學生 0 和學生 2 也是朋友,所以他們三個在一個朋友圈,返回 1。

題目思考

  1. 朋友圈的個數可以等價于什么呢?

解決方案

思路

  • 分析
    • 要求朋友圈個數, 我們只需要找到是朋友的學生, 把他們歸類在一起即可, 最終朋友圈就是集合的個數
  • 推導
    • 由于朋友關系是相互的, 具有對稱性, 所以我們只需要遍歷單方朋友關系即可, 即只需要遍歷 i=>j(i<=j)的關系
    • 然后對于朋友關系, 將兩者 union 起來即可
    • 最后再遍歷所有人找他們的祖先 (注意此處仍然需要調用 find 而不是直接拿 pre 字典中存的結果, 具體原因參見上篇文章[Leetcode 每日精選](本周主題-并查集) 990. 等式方程的可滿足性), 把祖先放到集合里, 最后集合長度即為所求.
  • 實現
    • 下面的代碼中對每個步驟都有注釋, 方便大家理解

復雜度

  • 時間復雜度 O(N^2logN): 需要兩重循環, 然后每次帶有路徑壓縮的并查集的操作復雜度為 O(logN)
  • 空間復雜度 O(N): pre 字典中存 N 個元素

代碼

Python 3

class Solution:def findCircleNum(self, M: List[List[int]]) -> int:# 經典并查集模板# 祖先字典pre = {}def find(x):# 找x的祖先if x not in pre:# 祖先設為本身pre[x] = xelif pre[x] != x:# 路徑壓縮, 更新當前祖先到更上面的祖先pre[x] = find(pre[x])return pre[x]def union(x, y):# 合并x和y到同一集合, 即把x的祖先的祖先指向y的祖先pre[find(x)] = find(y)n = len(M)for i in range(n):for j in range(i, n):# 由于對稱性, M[j][i]一定也是1, 所以此處只需要合并i和j即可, j不需要從頭開始if M[i][j] == 1:union(i, j)cntset = set()for i in range(n):# 注意這里使用find得到每個節點的最終祖先cntset.add(find(i))return len(cntset)

C++

class Solution {
public:int findCircleNum(vector<vector<int>>& M) {unordered_map<int, int> pre;function<int(int)> find = [&](int x) {if (pre.find(x) == pre.end()) {pre[x] = x;} else if (pre[x] != x) {pre[x] = find(pre[x]);}return pre[x];};auto Union = [&](int x, int y) {pre[find(x)] = find(y);};for (int i = 0; i < M.size(); ++i) {for (int j = i; j < M.size(); ++j) {if (M[i][j]) {Union(i, j);}}}unordered_set<int> cntset;for (int i = 0; i < M.size(); ++i) {cntset.insert(find(i));}return cntset.size();}
};

大家可以在下面這些地方找到我~
我的知乎專欄
我的 CSDN
我的 Leetcode
我的牛客網博客
我的公眾號: 每日精選算法題, 歡迎大家掃碼關注~

總結

以上是生活随笔為你收集整理的并查集c++代码_[Leetcode 每日精选](本周主题-并查集) 547. 朋友圈的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。