Linux Python專案常用指令
阿新 • • 發佈:2021-01-17
技術標籤:LeetCode刷題
連結:https://leetcode-cn.com/problems/number-of-provinces/
有n
個城市,其中一些彼此相連,另一些沒有相連。如果城市a
與城市b
直接相連,且城市b
與城市c
直接相連,那麼城市a
與城市c
間接相連。
省份是一組直接或間接相連的城市,組內不含其他沒有相連的城市。
給你一個n x n
的矩陣isConnected
,其中isConnected[i][j] = 1
表示第i
個城市和第j
個城市直接相連,而isConnected[i][j] = 0
表示二者不直接相連。
返回矩陣中省份的數量。
示例 1:
輸入:isConnected = [[1,1,0],[1,1,0],[0,0,1]] 輸出:2
示例 2:
輸入:isConnected = [[1,0,0],[0,1,0],[0,0,1]] 輸出:3
提示:
1 <= n <= 200
n == isConnected.length
n == isConnected[i].length
isConnected[i][j]
為1
或0
isConnected[i][i] == 1
isConnected[i][j] == isConnected[j][i]
思路:是一個很明顯的並查集問題,開始時是n個獨立的集合,每合併一次,集合數就減少1。我們用路徑壓縮排行優化(增加按秩合併也可以,但是如果時間不是卡的特別死,按秩合併的優化力度有限,反而會提高程式碼複雜度)。
class Solution { public: int Father[210]; int Find(int x){ if( x != Father[x] ){ return Father[x] = Find(Father[x]); } return Father[x]; } void Union(int A,int B,int &Single){ int FA = Find(A), FB = Find(B); if( FA != FB ){ Father[FA] = FB; -- Single;//每成功合併一次 集合數就少一 } } int findCircleNum(vector<vector<int>>& isConnected) { int n = isConnected.size(), i, j, Single = n; for(i = 0; i < n; ++ i){ Father[i] = i; } for(i = 0; i < n; ++ i){ for(j = 0; j < n; ++ j){ if( isConnected[i][j] ){ Union(i, j, Single); } } } return Single; } };
增加按秩合併版:
class Solution {
public:
int Father[210];
int Rank[210];
int Find(int x){
if( x != Father[x] ){
return Father[x] = Find(Father[x]);
}
return Father[x];
}
void Union(int A,int B,int &Single){
int FA = Find(A), FB = Find(B);
if( FA != FB ){
if(Rank[FA] < Rank[FB]){
Father[FA] = FB;
}else if(Rank[FA] == Rank[FB]){
Father[FA] = FB;
++ Rank[FB];
}else{
Father[FB] = FA;
}
-- Single;//每成功合併一次 集合數就少一
}
}
int findCircleNum(vector<vector<int>>& isConnected) {
int n = isConnected.size(), i, j, Single = n;
memset(Rank,0,sizeof(Rank));
for(i = 0; i < n; ++ i){
Father[i] = i;
}
for(i = 0; i < n; ++ i){
for(j = 0; j < n; ++ j){
if( isConnected[i][j] ){
Union(i, j, Single);
}
}
}
return Single;
}
};
這種寫法是為了保證Rank正確反映樹的高度,但同時過於複雜的if-else語句是會降低程式執行效能的,如果我們不需要保證Rank的正確性,則可以:
class Solution {
public:
int Father[210];
int Rank[210];
int Find(int x){
if( x != Father[x] ){
return Father[x] = Find(Father[x]);
}
return Father[x];
}
void Union(int A,int B,int &Single){
int FA = Find(A), FB = Find(B);
if( FA != FB ){
if(Rank[FA] < Rank[FB]){
Father[FA] = FB;
++ Rank[FB];
}else{
Father[FB] = FA;
++ Rank[FA];
}
-- Single;//每成功合併一次 集合數就少一
}
}
int findCircleNum(vector<vector<int>>& isConnected) {
int n = isConnected.size(), i, j, Single = n;
memset(Rank,0,sizeof(Rank));
for(i = 0; i < n; ++ i){
Father[i] = i;
}
for(i = 0; i < n; ++ i){
for(j = 0; j < n; ++ j){
if( isConnected[i][j] ){
Union(i, j, Single);
}
}
}
return Single;
}
};