【算法提升班】並查集

關於並查集的題目很多,官方給的數據是 30 道(截止 2020-02-20),可是有一些題目雖然官方沒有貼並查集標籤,可是使用並查集來講確很是簡單。這類題目若是掌握模板,那麼刷這種題會很是快,而且犯錯的機率會大大下降,這就是模板的好處。python

我這裏總結了幾道並查集的題目:算法

你們能夠學了模板以後去套用一下上面的三道題,作不出來的能夠看看個人題解。segmentfault

並查集概述

並查集算法,主要是解決圖論中「動態連通性」問題的性能

Union-Find 算法解決的是圖的動態連通性問題,這個算法自己不難,能不能應用出來主要是看你抽象問題的能力,是否可以把原始問題抽象成一個有關圖論的問題。spa

若是你對這個算法不是很明白,推薦看一下這篇文章Union-Find 算法詳解,講的很是詳細。code

你能夠把並查集的元素當作部門的人,幾我的能夠組成一個部門個數。blog

並查集核心的三個方法分別是union, find, connectedci

  • union: 將兩我的所在的兩個部門合併成一個部門(若是兩我的是相同部門,實際山不須要合併)


(圖來自 labuladong)leetcode

  • find: 查找某我的的部門 leader
  • connnected: 判斷兩我的是不是一個部門的


(圖來自 labuladong)get

模板

這是一個我常常使用的模板,我會根據具體題目作細小的變化,可是大致是不變的。

class UF:
    parent = {}
    cnt = 0
    def __init__(self, M):
        # 初始化 parent 和 cnt

    def find(self, x):
        while x != self.parent[x]:
            x = self.parent[x]
        return x
    def union(self, p, q):
        if self.connected(p, q): return
        self.parent[self.find(p)] = self.find(q)
        self.cnt -= 1
    def connected(self, p, q):
        return self.find(p) == self.find(q)

若是你想要更好的性能,這個模板更適合你,相應地代碼稍微有一點複雜。

class UF:
    parent = {}
    size = {}
    cnt = 0
    def __init__(self, M):
        # 初始化 parent,size 和 cnt

    def find(self, x):
        while x != self.parent[x]:
            x = self.parent[x]
            # 路徑壓縮
            self.parent[x] = self.parent[self.parent[x]];
        return x
    def union(self, p, q):
        if self.connected(p, q): return
        # 小的樹掛到大的樹上, 使樹儘可能平衡
        leader_p = self.find(p)
        leader_q = self.find(q)
        if self.size[leader_p] < self.size[leader_q]:
            self.parent[leader_p] = leader_q
        else:
            self.parent[leader_q] = leader_p
        self.cnt -= 1
    def connected(self, p, q):
        return self.find(p) == self.find(q)

你們能夠根據狀況使用不一樣的模板。

相關文章
相關標籤/搜索