1042. 不臨接植花(Python)

難度:★★★☆☆
類型:圖
方法:貪心

題目

力扣鏈接請移步本題傳送門
更多力扣中等題的解決方案請移步力扣中等題目錄

有 n 個花園晒骇,按從 1 到 n 標記杉女。另有數(shù)組 paths 庆尘,其中 paths[i] = [xi, yi] 描述了花園 xi 到花園 yi 的雙向路徑地梨。在每個花園中瞬痘,你打算種下四種花之一伐庭。

另外顽照,所有花園 最多 有 3 條路徑可以進入或離開.

你需要為每個花園選擇一種花无畔,使得通過路徑相連的任何兩個花園中的花的種類互不相同。

以數(shù)組形式返回 任一 可行的方案作為答案 answer参袱,其中 answer[i] 為在第 (i+1) 個花園中種植的花的種類电谣』嗝罚花的種類用 1、2辰企、3风纠、4 表示。保證存在答案牢贸。

示例 1:

輸入:n = 3, paths = [[1,2],[2,3],[3,1]]
輸出:[1,2,3]
解釋:
花園 1 和 2 花的種類不同。
花園 2 和 3 花的種類不同镐捧。
花園 3 和 1 花的種類不同潜索。
因此,[1,2,3] 是一個滿足題意的答案懂酱。其他滿足題意的答案有 [1,2,4]竹习、[1,4,2] 和 [3,2,1]

示例 2:

輸入:n = 4, paths = [[1,2],[3,4]]
輸出:[1,2,1,2]

示例 3:

輸入:n = 4, paths = [[1,2],[2,3],[3,4],[4,1],[1,3],[2,4]]
輸出:[1,2,3,4]

提示:

1 <= n <= 104
0 <= paths.length <= 2 * 104
paths[i].length == 2
1 <= xi, yi <= n
xi != yi
每個花園 最多 有 3 條路徑可以進入或離開

解答

我們把花園看成結點,聯(lián)系各個結點的路徑用數(shù)組集合的方式給出列牺,很容易想到用深度優(yōu)先搜索或寬度優(yōu)先搜索的方法探索連通域整陌。

解法1:深度優(yōu)先搜索

第一步,建圖瞎领。

為了便于表達泌辫,我們把用字典的形式存儲每個結點的臨近結點。這里需要注意的是九默,為了便于python索引震放,我們把每個花園編號減1,將1到n范圍轉到了0到n-1范圍驼修。graph[node]是一個列表殿遂,里面是與node結點相鄰的所有結點。

第二步乙各,染色列表墨礁。

為了存儲每個花園的染色結果,我們準備一個列表color_of_耳峦,color_of_[node]表示node結點被染色的結果恩静,列表長度為n,默認值為0妇萄,每個位置將要被染色成1,2,3,4中的一個蜕企。

第三步,深度優(yōu)先搜索冠句。

定義深度優(yōu)先搜索函數(shù)實現(xiàn)循環(huán)染色轻掩。函數(shù)有兩個輸入,一個是結點node懦底,一個是該結點需要被染色的結果color唇牧,函數(shù)返回值是布爾量罕扎,表達能否成功染色。函數(shù)過程中執(zhí)行染色操作丐重。

入口處需要優(yōu)先判斷是否能被染色腔召,遍歷node的每個相鄰結點,如果發(fā)現(xiàn)任何一個相鄰結點已經(jīng)被染色為color扮惦,則染色失敗臀蛛,直接返回False。

如果通過了上面的校驗崖蜜,則可以將該結點染色浊仆,color_of_[node] = color,接下來就是把node的臨近結點neighbor染色豫领,這里需要注意顏色的選擇抡柿。我們需要選擇除了color以外的所有顏色,將這些顏色分別做嘗試等恐,一旦嘗試成功洲劣,則不再進行其他顏色的嘗試。臨近結點neighbor的選擇也有講究课蔬,如果該節(jié)點已經(jīng)被染了色囱稽,也就是該節(jié)點處color_of_對應位置處的值不是零,該節(jié)點是不需要再考慮的购笆。如果所有臨近結點都完成染色粗悯,則dfs返回值記得設置為True,代表node結點染色成功同欠。

第四步样傍,遍歷。

接下來就是使用dfs函數(shù)的時候铺遂。我們有必要遍歷每一個結點衫哥,一旦某結點沒有被染色(通過color_of_[node] 是否為零判斷),則調(diào)用dfs函數(shù)進行染色襟锐,顏色的選擇與上面類似撤逢,需要進行嘗試。

題目的解答過程實際上就是color_of_的填充過程粮坞,所有結點遍歷完成后蚊荣,如果發(fā)現(xiàn)color_of_中還有沒有被染色的結點,也就是0 in color_of_莫杈,則說明無法完成所有結點的染色互例,否則,直接返回染色結果筝闹。

編程中其他注意事項:

第一媳叨,為了給字典提供默認值腥光,我們使用defaultdict類;

第二糊秆,dfs函數(shù)的設計過程中武福,需要將終止條件寫在開頭。

from collections import defaultdict


class Solution:
    def gardenNoAdj(self, n, paths):
        graph = defaultdict(set)
        for u, v in paths:
            u, v = u - 1, v - 1
            graph[u].add(v)
            graph[v].add(u)

        color_of_ = [0] * n
        colors = {1, 2, 3, 4}

        def dfs(node, color):
            for neighbor in graph[node]:
                if color_of_[neighbor] == color:
                    return False
            color_of_[node] = color

            for color in colors - {color}:
                for neighbor in graph[node]:
                    if color_of_[neighbor] == 0 and dfs(neighbor, color):
                        return True
            return True

        for node in range(n):
            if color_of_[node] == 0:
                for color in colors:
                    if dfs(node, color):
                        break

        if 0 in color_of_:
            return "Unable for color!"
        return color_of_


s = Solution()
print(s.gardenNoAdj(3, [[1,2],[2,3],[3,1]]))
print(s.gardenNoAdj(4,  [[1,2],[3,4]]))
print(s.gardenNoAdj(4, [[1,2],[2,3],[3,4],[4,1],[1,3],[2,4]]))
print(s.gardenNoAdj(5, [[1, 2], [1, 3], [1, 4], [1, 5],
                        [2, 3], [2, 4], [2, 5],
                        [3, 4], [3, 5],
                        [4, 5],
                        ]))

解法2:貪心

因為題目已經(jīng)告訴了我們痘番,染色是一定可以成功的捉片,我們就可以直接放心的填充每一個結點了。最關鍵的填充什么顏色夫偶。對于某一個結點node界睁,其顏色需要根據(jù)臨近結點填充,而且有的臨近結點已經(jīng)被填充過了兵拢,有的沒有,我們只需要考慮被填充過的那些就好逾礁,需要保證該結點的顏色與那些已經(jīng)被填充過的結點顏色都不同说铃,至于到底填什么顏色,隨便彈出一個滿足條件的就夠了嘹履。只要每填充一個結點腻扇,都按照上面的法則,則填充結果一定是滿足要求的砾嫉。這樣在寫法上是非常簡單的幼苛。

python里通過集合相減的操作實現(xiàn)剩余顏色的獲取。

from collections import defaultdict
from typing import List


class Solution:
    def gardenNoAdj(self, n: int, paths: List[List[int]]) -> List[int]:
        graph = defaultdict(list)
        for u, v in paths:
            u, v = u - 1, v - 1
            graph[u].append(v)
            graph[v].append(u)
        ans = [0] * n
        for u in range(n):
            colors = {1, 2, 3, 4} - set(ans[v] for v in graph[u])
            ans[u] = colors.pop()
        return ans

如有疑問或建議焕刮,歡迎評論區(qū)留言~

有關更多力扣中等題的python解決方案舶沿,請移步力扣中等題解析

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市配并,隨后出現(xiàn)的幾起案子括荡,更是在濱河造成了極大的恐慌,老刑警劉巖溉旋,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畸冲,死亡現(xiàn)場離奇詭異,居然都是意外死亡观腊,警方通過查閱死者的電腦和手機邑闲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來梧油,“玉大人苫耸,你說我怎么就攤上這事∩羲荩” “怎么了鲸阔?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵偷霉,是天一觀的道長。 經(jīng)常有香客問我褐筛,道長类少,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任渔扎,我火速辦了婚禮硫狞,結果婚禮上,老公的妹妹穿的比我還像新娘晃痴。我一直安慰自己残吩,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布倘核。 她就那樣靜靜地躺著泣侮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪紧唱。 梳的紋絲不亂的頭發(fā)上活尊,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機與錄音漏益,去河邊找鬼蛹锰。 笑死,一個胖子當著我的面吹牛绰疤,可吹牛的內(nèi)容都是我干的铜犬。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼轻庆,長吁一口氣:“原來是場噩夢啊……” “哼癣猾!你這毒婦竟也來了?” 一聲冷哼從身側響起榨了,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤煎谍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后龙屉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體呐粘,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年转捕,在試婚紗的時候發(fā)現(xiàn)自己被綠了作岖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡五芝,死狀恐怖痘儡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情枢步,我是刑警寧澤沉删,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布渐尿,位于F島的核電站,受9級特大地震影響矾瑰,放射性物質(zhì)發(fā)生泄漏砖茸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一殴穴、第九天 我趴在偏房一處隱蔽的房頂上張望凉夯。 院中可真熱鬧,春花似錦采幌、人聲如沸劲够。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽征绎。三九已至,卻和暖如春磨取,著一層夾襖步出監(jiān)牢的瞬間炒瘸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工寝衫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拐邪。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓慰毅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親扎阶。 傳聞我的和親對象是個殘疾皇子汹胃,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容