[LeetCode] All Paths From Source to Target 從起點到目標點到所有路徑
Given a directed, acyclic graph of N
nodes. Find all possible paths from node 0
to node N-1
, and return them in any order.
The graph is given as follows: the nodes are 0, 1, ..., graph.length - 1. graph[i] is a list of all nodes j for which the edge (i, j) exists.
Example: Input: [[1,2], [3], [3], []] Output: [[0,1,3],[0,2,3]] Explanation: The graph looks like this: 0--->1 | | v v 2--->3 There are two paths: 0 -> 1 -> 3 and 0 -> 2 -> 3.
Note:
- The number of nodes in the graph will be in the range
[2, 15]
. - You can print different paths in any order, but you should keep the order of nodes inside one path.
這道題給了我們一個無迴路有向圖,包含N個結點,然後讓我們找出所有可能的從結點0到結點N-1的路徑。這個圖的資料是通過一個類似鄰接連結串列的二維陣列給的,最開始的時候博主沒看懂輸入資料的意思,其實很簡單,我們來看例子中的input,[[1,2], [3], [3], []],這是一個二維陣列,最外層的數組裡面有四個小陣列,每個小陣列其實就是和當前結點相通的鄰結點,由於是有向圖,所以只能是當前結點到鄰結點,反過來不一定行。那麼結點0的鄰結點就是結點1和2,結點1的鄰結點就是結點3,結點2的鄰結點也是3,結點3沒有鄰結點。那麼其實這道題的本質就是遍歷鄰接連結串列,由於要列出所有路徑情況,那麼遞迴就是不二之選了。我們用cur來表示當前遍歷到的結點,初始化為0,然後在遞迴函式中,先將其加入路徑path,如果cur等於N-1了,那麼說明到達結點N-1了,將path加入結果res。否則我們再遍歷cur的鄰接結點,呼叫遞迴函式即可,參見程式碼如下:
解法一:
class Solution { public: vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) { vector<vector<int>> res; helper(graph, 0, {}, res); return res; } void helper(vector<vector<int>>& graph, intcur, vector<int> path, vector<vector<int>>& res) { path.push_back(cur); if (cur == graph.size() - 1) res.push_back(path); else for (int neigh : graph[cur]) helper(graph, neigh, path, res); } };
下面這種解法也是遞迴,不過寫法稍有不同,遞迴函式直接返回結果,這樣引數就少了許多,但是思路還是一樣的,如果cur等於N-1了,直接將cur先裝入陣列,再裝入結果res中返回。否則就遍歷cur的鄰接結點,對於每個鄰接結點,先呼叫遞迴函式,然後遍歷其返回的結果,對於每個遍歷到的path,將cur加到陣列首位置,然後將path加入結果res中即可,這有點像是回溯的思路,路徑是從後往前組成的,參見程式碼如下:
解法二:
class Solution { public: vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) { return helper(graph, 0); } vector<vector<int>> helper(vector<vector<int>>& graph, int cur) { if (cur == graph.size() - 1) { return {{graph.size() - 1}}; } vector<vector<int>> res; for (int neigh : graph[cur]) { for (auto path : helper(graph, neigh)) { path.insert(path.begin(), cur); res.push_back(path); } } return res; } };
類似題目: