問題的本質就是讓你在一幅「圖」中找到從起點start到終點target的最近距離,這個例子聽起來很枯燥,但是 bfs 演算法問題其實都是在幹這個事兒。
把枯燥的本質搞清楚了,再去欣賞各種問題的包裝才能胸有成竹嘛。
這個廣義的描述可以有各種變體,比如走迷宮,有的格仔是圍牆不能走,從起點到終點的最短距離是多少?如果這個迷宮帶「傳送門」可以瞬間傳送呢?
再比如說兩個單詞,要求你通過某些替換,把其中乙個變成另乙個,每次只能替換乙個字元,最少要替換幾次?
再比如說連連看遊戲,兩個方塊消除的條件不僅僅是圖案相同,還得保證兩個方塊之間的最短連線不能多於兩個拐點。你玩連連看,點選兩個座標,遊戲是如何判斷它倆的最短連線有幾個拐點的?
再比如……
淨整些花裡胡哨的,這些問題都沒啥奇技淫巧,本質上就是一幅「圖」,讓你從乙個起點,走到終點,問最短路徑。這就是 bfs 的本質,框架搞清楚了直接默寫就好。
①樹的層序遍歷:使用佇列儲存未被檢測的結點,結點按照寬度優先的次序被訪問和進出隊。
②有向無環圖的最短路徑查詢:由於有向無環圖的某個節點的next節點可能會與另乙個節點的next節點重複,所以我們需要記錄已訪問過的節點
//根節點與目標節點之間的最短路徑長度
一直往深處走,直到找到解或者走不下去為止,主要用於樹的遍歷(前序遍歷,中序遍歷,後序遍歷)或者圖的搜尋問題或者回溯演算法問題。
①樹的遍歷:一直向葉子節點遍歷,直至遇到葉子節點表示此根節點到這個葉子節點的路徑已經訪問完,需要訪問根節點到下乙個葉子節點的路徑。(當然遍歷順序主要取決於遍歷的方式,比如前序遍歷(根左右)、後序遍歷(左根右)、後序遍歷(左右根))
②圖的搜尋問題:上面我們使用了bfs來解決圖的最短路徑問題,同時我們也可以使用dfs來實現圖的最短路徑尋找。在這裡我們分別提供遞迴版模板和用stack的迭代版模板:
遞迴:
boolean dfs(node cur, node target, setvisited)
}return false;
}
非遞迴:
boolean dfs(int root, int target)
}remove cur from s;
}return false;
}
回溯法:回溯法使用dfs的策略來尋找所有可行解或者最優解,也就是回溯法的所有解可以構成乙個解空間樹或者解空間圖,所以對於這個解空間樹或圖,我們就使用dfs策略了
//choicelist:表示可以進行選擇的列表,相當於樹中可選用左節點還是右結點
//track:表示為決策路徑,相當於在樹中為根節點到某個葉子節點的路徑
//result:表示存放根節點到所有葉子節點的所有路徑
backtrack(choicelist,track,result)
}
應用與風險:
1)dfs多用於連通性問題因為其執行思想與人腦的思維很相似,故解決連通性問題更自然。
2)bfs多用於解決最短路問題,其執行過程中需要儲存每一層的資訊,所以其執行時需要儲存的資訊量較大,如果人腦也可儲存大量資訊的話,理論上人腦也可執行bfs。
3)多數情況執行bfs所需的記憶體會大於dfs需要的記憶體(dfs一次訪問一條路,bfs一次訪問多條路)
4)風險:dfs容易爆棧(棧不易」控制」),bfs通過控制佇列可以很好解決」爆佇列」風險。
Leetcode刷題之括號
給定乙個只包括 的字串,判斷字串是否有效。有效字串需滿足 左括號必須用相同型別的右括號閉合。左括號必須以正確的順序閉合。注意空字串可被認為是有效字串。示例 1 輸入 輸出 true 示例 2 輸入 輸出 true 示例 3 輸入 輸出 false 示例 4 輸入 輸出 false 示例 5 輸入 輸...
leetcode刷題之堆
今天終於開啟的第二個專題的刷題之旅堆,不過第乙個專題棧還有乙個小問題沒解決就是利用遞減棧去解決接雨水的問題,雖然那道題我用動態規劃的問題解決出來了,我記得看到過一道面試題,問棧和堆有什麼區別。通過搜尋網上的資料總結如下。棧 stack 由系統分配記憶體,速度較快,但是自己無法掌握。堆 一般用兩種方法...
leetcode刷題之樹
樹的三種遍歷方式 的 非遞迴版本 中序遍歷 下面的解法就是相當於 第一趟先把元素按照中序的順序進棧 第二趟 是相當於把 null標記過的位置給拿出來 class solution else return res 先序遍歷 class solution else return res 公共父節點 pu...