LeetCode 133. 克隆圖 | Python

133. 克隆圖


題目來源:力扣(LeetCode)
https://leetcode-cn.com/problems/clone-graph

題目


給你無向 連通 圖中一個節(jié)點的引用,請你返回該圖的 深拷貝(克鲁)秦爆。

圖中的每個節(jié)點都包含它的值 val(int) 和其鄰居的列表(list[Node])捏检。

class Node {
    public int val;
    public List<Node> neighbo rs;
}

測試用例格式:

簡單起見,每個節(jié)點的值都和它的索引相同氢橙。例如氮墨,第一個節(jié)點值為 1(val = 1),第二個節(jié)點值為 2(val = 2)算利,以此類推。該圖在測試用例中使用鄰接列表表示寇蚊。

鄰接列表 是用于表示有限圖的無序列表的集合笔时。每個列表都描述了圖中節(jié)點的鄰居集棍好。

給定節(jié)點將始終是圖中的第一個節(jié)點(值為 1)仗岸。你必須將 給定節(jié)點的拷貝 作為對克隆圖的引用返回允耿。

示例 1:

示例 1
輸入:adjList = [[2,4],[1,3],[2,4],[1,3]]
輸出:[[2,4],[1,3],[2,4],[1,3]]
解釋:
圖中有 4 個節(jié)點。
節(jié)點 1 的值是 1扒怖,它有兩個鄰居:節(jié)點 2 和 4 较锡。
節(jié)點 2 的值是 2,它有兩個鄰居:節(jié)點 1 和 3 盗痒。
節(jié)點 3 的值是 3蚂蕴,它有兩個鄰居:節(jié)點 2 和 4 。
節(jié)點 4 的值是 4俯邓,它有兩個鄰居:節(jié)點 1 和 3 骡楼。

示例 2:

示例 2
輸入:adjList = [[]]
輸出:[[]]
解釋:輸入包含一個空列表。該圖僅僅只有一個值為 1 的節(jié)點稽鞭,它沒有任何鄰居鸟整。

示例 3:

輸入:adjList = []
輸出:[]
解釋:這個圖是空的,它不含任何節(jié)點朦蕴。

示例 4:

示例 4
輸入:adjList = [[2],[1]]
輸出:[[2],[1]]

提示:

  • 節(jié)點數(shù)不超過 100 篮条。
  • 每個節(jié)點值 Node.val 都是唯一的,1 <= Node.val <= 100吩抓。
  • 無向圖是一個簡單圖涉茧,這意味著圖中沒有重復(fù)的邊,也沒有自環(huán)疹娶。
  • 由于圖是無向的伴栓,如果節(jié)點 p 是節(jié)點 q 的鄰居,那么節(jié)點 q 也必須是節(jié)點 p 的鄰居蚓胸。
  • 圖是連通圖挣饥,你可以從給定節(jié)點訪問到所有節(jié)點。

解題思路


思路:DFS沛膳、BFS

在這道題中扔枫,題目要求的是圖的深拷貝。題目所述的圖的深拷貝锹安,其實就是要構(gòu)建與原圖結(jié)構(gòu)短荐,值均一樣的圖,但是 其中的節(jié)點不能再是原圖的引用叹哭。

題目開頭說了忍宋,給定的是一個節(jié)點的引用。但后面的提示也提及风罩,圖是連通的糠排,可以從給定的節(jié)點中去訪問所有節(jié)點。那么我們在進(jìn)行訪問搜索的時候超升,完成圖的深拷貝入宦。

深度優(yōu)先搜索(DFS)

這里先說下需要注意的地方哺徊,因為題目中明確說了,圖是無向圖乾闰,圖中的邊是無向邊落追。例如示例 4:

示例 4

這里節(jié)點 1 和節(jié)點 2 存在無向邊,也就是說節(jié)點 1 可以到節(jié)點 2涯肩,而節(jié)點 2 也可以到 節(jié)點 1轿钠。所以我們遍歷搜索的時候要注意標(biāo)記,否則的話容易陷入死循環(huán)病苗。

下面是具體算法:

  • 前面說在遍歷訪問的時候進(jìn)行標(biāo)記疗垛,這里我們借助哈希表來已經(jīng)被訪問和克隆的節(jié)點。其中鍵表示的是原圖的節(jié)點硫朦,而值表示的是克隆圖中對應(yīng)的節(jié)點继谚;
  • 從給定的節(jié)點開始向下搜索,如果節(jié)點存在于哈希表中阵幸,那么直接返回哈希表中的對應(yīng)的節(jié)點花履;
  • 如果節(jié)點并沒有被標(biāo)記,那么創(chuàng)建克隆節(jié)點挚赊,存儲到哈希表中诡壁;
  • 遞歸調(diào)用每個節(jié)點的鄰接點,將結(jié)果放到克隆鄰接點列表中荠割。

具體的代碼見【代碼實現(xiàn) # 深度優(yōu)先搜索】

廣度優(yōu)先搜索(BFS)

使用廣度優(yōu)先搜索妹卿,這里同樣需要注意無向邊的問題。在這里蔑鹦,同樣使用哈希表來存儲已被訪問原圖的節(jié)點以及對應(yīng)克隆節(jié)點夺克。下面是具體的算法:

  • 使用哈希表來存儲已被訪問原圖的節(jié)點以及對應(yīng)克隆節(jié)點;
  • 克隆給定的節(jié)點嚎朽,存儲到哈希表中铺纽。同時借助輔助隊列,先將給定的節(jié)點放到隊列哟忍。
  • 出隊狡门,訪問該節(jié)點的所有鄰接點。如果節(jié)點不在哈希表中锅很,那么克隆當(dāng)前節(jié)點的鄰接點存入哈希表中其馏。同時將此鄰接點入隊,并將此鄰接點放到克隆圖中對應(yīng)節(jié)點的鄰接表中爆安。
  • 重復(fù)直至隊列為空叛复,表明圖遍歷結(jié)束。

具體的代碼見【代碼實現(xiàn) # 廣度優(yōu)先搜索】

代碼實現(xiàn)


# 深度優(yōu)先搜索
"""
# Definition for a Node.
class Node:
    def __init__(self, val = 0, neighbors = []):
        self.val = val
        self.neighbors = neighbors
"""

class Solution:
    def cloneGraph(self, node: 'Node') -> 'Node':
        marked = {}

        def dfs(node):
            if not node:
                return node
            # 如果存在于哈希表中,直接返回哈希表存儲的值
            if node in marked:
                return marked[node]
            
            # 不存在哈希表中褐奥,那么克隆節(jié)點肤寝,將其放入哈希表中
            clone_node = Node(node.val, [])
            marked[node] = clone_node
            # 遍歷節(jié)點的鄰接點,相鄰接點放到鄰接列表中
            for neighbor in node.neighbors:
                clone_node.neighbors.append(dfs(neighbor))
            
            return clone_node
        
        return dfs(node)

# 廣度優(yōu)先搜索
"""
# Definition for a Node.
class Node:
    def __init__(self, val = 0, neighbors = []):
        self.val = val
        self.neighbors = neighbors
"""

class Solution:
    def cloneGraph(self, node: 'Node') -> 'Node':
        from collections import deque

        marked = {}

        def bfs(node):
            if not node:
                return node
            # 克隆節(jié)點抖僵,放到哈希表中
            clone_node = Node(node.val, [])
            marked[node] = clone_node
            # 先將給定的節(jié)點入隊
            queue = deque()
            queue.append(node)
            
            # 出隊,開始遍歷
            while queue:
                cur_node = queue.popleft()
                for neighbor in cur_node.neighbors:
                    # 如果鄰接點不在哈希表中缘揪,克隆鄰接點存入哈希表中耍群,并將鄰接點入隊
                    if neighbor not in marked:
                        marked[neighbor] = Node(neighbor.val, [])
                        queue.append(neighbor)
                    # 更新當(dāng)前節(jié)點的鄰接列表,注意是克隆節(jié)點
                    marked[cur_node].neighbors.append(marked[neighbor])
            return clone_node
        
        return bfs(node)

實現(xiàn)結(jié)果


實現(xiàn)結(jié)果 | 深度優(yōu)先搜索
實現(xiàn)結(jié)果 | 廣度優(yōu)先搜索

歡迎關(guān)注


公眾號 【書所集錄

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末找筝,一起剝皮案震驚了整個濱河市蹈垢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌袖裕,老刑警劉巖曹抬,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異急鳄,居然都是意外死亡谤民,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門疾宏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來张足,“玉大人,你說我怎么就攤上這事坎藐∥梗” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵岩馍,是天一觀的道長碉咆。 經(jīng)常有香客問我,道長蛀恩,這世上最難降的妖魔是什么疫铜? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮双谆,結(jié)果婚禮上块攒,老公的妹妹穿的比我還像新娘。我一直安慰自己佃乘,他們只是感情好囱井,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著趣避,像睡著了一般庞呕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天住练,我揣著相機(jī)與錄音地啰,去河邊找鬼。 笑死讲逛,一個胖子當(dāng)著我的面吹牛亏吝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盏混,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼蔚鸥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了许赃?” 一聲冷哼從身側(cè)響起止喷,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎混聊,沒想到半個月后弹谁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡句喜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年预愤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咳胃。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡鳖粟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拙绊,到底是詐尸還是另有隱情向图,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布标沪,位于F島的核電站榄攀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏金句。R本人自食惡果不足惜檩赢,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望违寞。 院中可真熱鬧贞瞒,春花似錦、人聲如沸趁曼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挡闰。三九已至乒融,卻和暖如春掰盘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赞季。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工愧捕, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人申钩。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓次绘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親撒遣。 傳聞我的和親對象是個殘疾皇子邮偎,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359