1. 程式人生 > >[LeetCode] All Paths From Source to Target 從起點到目標點到所有路徑

[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, int
cur, 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;
    }
};

類似題目: