1. 程式人生 > >LeetCode--所有可能的路徑

LeetCode--所有可能的路徑

class Solution {

public:

vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {

vector<vector<int>> ret;

int num = graph.size() - 1;

vector<int> path;

AllPath(graph, ret,path,0,num);

return ret;

}

void AllPath(vector<vector<int>>& graph, vector<vector<int>>& ret, vector<int> path,int begin,int num)

{

path.push_back(begin);

if (begin == num)

{

ret.push_back(path);

return;

}

for (int i = 0; i < graph[begin].size(); i++)

{

AllPath(graph, ret, path, graph[begin][i], num);

}

return;

}

};

 

  當拿到這個題的時候還是有一點點的思路,實在不行就暴力求解,但是這個題暴力求解是很複雜的,我看來是不能實現的,因為你不知道陣列有多少個一維陣列,並且每個一維數組裡邊的資料個數也是不能確定的。所以暴力求解是不能實現的。

  因為和迴圈類似的問題就是遞迴了,並且看到結點的數字會在範圍2,15內,那這不就是怕遞迴層數過多。所以自然就用遞迴來解決,

  在最初的遞迴中我想的是一層層往回退,你不是要到達num的節點麼,我先看num-1能不能到,能的話我再去看num-2能不能到num-1,但是這種遇到0直接到3這種情況處理起來就很麻煩。

  所以還是正著走好一點,正著走就要解決幾個問題。

  1. 當你走到最後的結點也就是目的地的時候你就需要停下來,這是遞迴的一個邊界條件。所以這就要求你函式的引數裡邊要有當前走到的結點,和最終目的地結點兩個引數

  2. 當你走到一半的時候發現這條路不能走的時候要返回。並且把走過的路徑不儲存。就比如你現在有一條路是1-2-3-5,但是你走到1-2的時候去了4結點,4不能到達5你要退回到2.

  3. 當你發現你當前節點就是你要到達的結點的時候要儲存當前的路徑陣列進去,並且還能退回去,可能還有其他可能, 比如上來直接有0-5的路徑,你還是要去遍歷0-1,0-2這些結點。

  其實在用遞迴寫問題的經常有感覺,我感覺自己寫的不是特別對就是能實現我想要的功能。這裡我們還是建立另外一個函式,因為提供的函式引數是不夠的。

void AllPath(vector<vector<int>>& graph, vector<vector<int>>& ret, vector<int> path,int begin,int num)

{

path.push_back(begin);

if (begin == num)

{

ret.push_back(path);

return;

}

for (int i = 0; i < graph[begin].size(); i++)

{

AllPath(graph, ret, path, graph[begin][i], num);

}

return;

}

 

自己最初的時候沒有想明白,這裡我認為最關鍵的地方就是vector<int> path,這裡不能用引用,這樣就不會如果這條路徑失敗了, 或者說這條路徑插入了新的路徑位置不會影響上層遞迴往其他下層函式傳遞的資料。

如果加上引用的話,會發現我們後邊的陣列會把前邊所有的路徑都儲存下來在再去加自己的路徑。

當我們的開始結點和我們最終想到達的結點相同的時候,就把這個拷貝出來的一維陣列path插入到二維數組裡邊,如果當我們的走到盡頭走不了但還沒到終點的時候就不會插入進入。