並查集的優化及應用

2022-08-11 10:06:12 字數 3506 閱讀 7738

2018-05-01 15:13:08

並查集是乙個時空複雜度非常優越的資料結構,並且通過優化後其複雜度為。

並查集的優化主要有兩個方面:

路徑壓縮:

按rank合併:

public class unionfindset 

}public int find(int i)

public boolean union(int i, int j)

return true;}}

問題描述:

問題求解:

樹形下的無向圖判斷環路問題,圖的描述方式是採用邊集。

並查集本身就是樹形結構,而樹是乙個無向圖,具體來說,樹是乙個無環的連通圖,所以本題可以直接使用並查集來進行求解。

public int findredundantconnection(int edges) 

}return res;

}

2019.04.21

public int findredundantconnection(int edges) 

}return null;

}private int find(int parent, int i)

return parent[i];

}private boolean union(int parent, int i, int j)

問題描述:

問題求解:

class solution 

}for (int i = 0; i < ufs.parent.length; i++)

if (ufs.parent[i] == i) res++;

return res;

}}class unionfindset

}public int find(int i)

public boolean union(int i, int j)

return true;}}

問題描述:問題求解:這裡有乙個o(n)的做法, 一次考慮兩個凳子,假設他們不為夫婦,為了讓這兩個位置坐的恰好是一對夫婦,那麼我們就需要調整其中乙個人的位置,如此調整直到所有的夫婦相鄰,交換的次數就是答案。下面給出證明。

將給定的row抽象成乙個n個頂點的無向圖(可能包含重邊),例如:

(_ _) (_ _) ... (_ _)

(v1 ) (v2 ) ... (vn )

vi和vj之間存在邊當且僅當vi和vj中存在一對夫婦,例如vi = (0,2),vj = (1, 4)存在一對夫婦(0, 1),而vi = (0, 2),vj = (1, 3)之間則存在兩對夫婦(0, 1)(2, 3),此vi和vj存在重邊。

考慮row陣列形成的無向圖,可以肯定要麼是孤立的單個節點,要麼是多個孤立的圈,例如row = [0, 1]是乙個孤立的點、row = [0, 2, 1, 3]則包含乙個圈v1, v2、row = [0, 3, 4, 1, 2, 5, 6, 8, 7, 9],包含兩個孤立的圈v1, v2, v3和v4, v5。

對於乙個圈來說,假設他有n個節點,那麼至少需要n-1次交換即可讓每個夫婦相鄰。有了這個結論,假定row陣列有n個點,m個孤立的圈,那麼至少需要n-m次交換即可。

public int minswapscouples(int row) 

return n - cnt;

}private int find(int parent, int i)

return parent[i];

}private boolean union(int parent, int i, int j)

問題描述:

問題求解:

這個問題可以轉化為求圖中連通數的問題,也就是經典的陸地數量問題。對於x | y相等的兩個石頭我們需要建立他們之間的聯絡。

經典的連通子樹問題可以使用dfs進行求解,從dfs的演算法過程我們可以看到其實是一棵以起始點為root的樹,因此,在這次dfs中我們總可以從葉子節點開始選取,知道最後只剩下root節點。

最終的答案就是所有的stones的數目 - 連通塊的數目。

這裡並不打算使用dfs來進行求解,將使用ufs來進行求解。

使用並查集並不需要那麼形式化的專門使用乙個類來進行表徵,這就是乙個簡單的資料結構,只需要在使用前進行定義就好了,另外,由於parent的數目範圍不確定,所以在很多時候使用陣列並不是乙個合適的選擇,使用hash表更能方便我們解決問題,本題就是使用hash表來進行的並查集的實現。

public int removestones(int stones) 

int cnt = 0;

for (int key : parent.keyset())

return n - cnt;

}private int find(mapparent, int i)

return parent.get(i);

}private boolean union(mapparent, int i, int j)

問題描述:問題求解:主要問題就是怎麼將字串的輸入進行轉化,這裡採用的轉化方式是將每個cell看成4個區域,0-3。根據不同的情況可以將各個區域進行合併,這樣本題就又變成了並查集問題。

int n;

public int regionsbyslashes(string grid)

if (grid[i].charat(j) != '\\') }}

return size;

}private int find(int parent, int i)

return parent[i];

}private boolean union(int parent, int i, int j)

private int getidx(int i, int j, int num)

並查集及優化 C

include include include include using namespace std 查詢快,但是合併差 class unionfind1 int find int p bool isconnected int p,int q void union int p,int q 基於2的...

並查集的實現及優化

並查集是一種用於在森林中判斷子圖數量及點的歸屬的資料結構,由於其特殊的路徑壓縮操作,使得這一過程可以異常地快。並查集主要由乙個pre陣列以及兩個函式組成 find函式和join函式。pre陣列表示每一節點的前驅,最終已完成的並查集,每乙個子圖的所有點只有乙個前驅 這也是其高效的原因 而初始化的並查集...

並查集的分析及應用

昨天看了幾篇有關並查集的 對理解並查集很有幫助,在這裡寫篇部落格來記錄下自己對並查集的簡單理解,以及並查集的簡單運用。並查集的分析 並查集的概念主要是處理集合問題 或可抽象成集合概念的問題 首先數學上的集合概念做個初步的分析 首先,我們從數學的角度給出等價關係和等價類的定義 定義1 如果集合s中的關...