日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

所有可能的路徑!

 mynotebook 2022-12-04 發(fā)布于湖南

通知:代碼隨想錄算法訓(xùn)練營(yíng) 五期開(kāi)始報(bào)名,預(yù)計(jì)下周三(12月7日)開(kāi)營(yíng)!

講完深度優(yōu)先搜索的理論基礎(chǔ)之后,今天來(lái)一個(gè)入門題目。

797.所有可能的路徑

力扣題目鏈接:https:///problems/all-paths-from-source-to-target/

給你一個(gè)有 n 個(gè)節(jié)點(diǎn)的 有向無(wú)環(huán)圖(DAG),請(qǐng)你找出所有從節(jié)點(diǎn) 0 到節(jié)點(diǎn) n-1 的路徑并輸出(不要求按特定順序)

graph[i] 是一個(gè)從節(jié)點(diǎn) i 可以訪問(wèn)的所有節(jié)點(diǎn)的列表(即從節(jié)點(diǎn) i 到節(jié)點(diǎn) graph[i][j]存在一條有向邊)。

圖片

提示:

  • n == graph.length
  • 2 <= n <= 15
  • 0 <= graph[i][j] < n
  • graph[i][j] != i(即不存在自環(huán))
  • graph[i] 中的所有元素 互不相同
  • 保證輸入為 有向無(wú)環(huán)圖(DAG)

思路

這道題目是深度優(yōu)先搜索,比較好的入門題。

如果對(duì)深度優(yōu)先搜索還不夠了解,可以先看這里:深度優(yōu)先搜索的理論基礎(chǔ)

我依然總結(jié)了深搜三部曲,如果按照代碼隨想錄刷題的錄友,應(yīng)該刷過(guò) 二叉樹(shù)的遞歸三部曲,回溯三部曲。

大家可能有疑惑,深搜 和 二叉樹(shù)和回溯算法 有什么區(qū)別呢?什么時(shí)候用深搜 什么時(shí)候用回溯?

我在講解二叉樹(shù)理論基礎(chǔ)(https:///二叉樹(shù)理論基礎(chǔ).html)的時(shí)候,提到過(guò),二叉樹(shù)的前中后序遍歷其實(shí)就是深搜在二叉樹(shù)這種數(shù)據(jù)結(jié)構(gòu)上的應(yīng)用。

那么回溯算法呢,其實(shí) 回溯算法就是深搜,只不過(guò) 我們給他一個(gè)更細(xì)分的定義,叫做回溯算法。

那有的錄友可能說(shuō):那我以后稱回溯算法為深搜,是不是沒(méi)毛?。?/p>

理論上來(lái)說(shuō),沒(méi)毛病,但 就像是  二叉樹(shù) 你不叫它二叉樹(shù),叫它數(shù)據(jù)結(jié)構(gòu),有問(wèn)題不?也沒(méi)問(wèn)題對(duì)吧。

建議是 有細(xì)分的場(chǎng)景,還是稱其細(xì)分場(chǎng)景的名稱。所以回溯算法可以獨(dú)立出來(lái),但回溯算法確實(shí)就是深搜。

接下來(lái)我們使用深搜三部曲來(lái)分析題目:

  1. 確認(rèn)遞歸函數(shù),參數(shù)

首先我們dfs函數(shù)一定要存一個(gè)圖,用來(lái)遍歷的,還要存一個(gè)目前我們遍歷的節(jié)點(diǎn),定義為x

至于 單一路徑,和路徑集合可以放在全局變量,那么代碼是這樣的:

vector<vector<int>> result; // 收集符合條件的路徑
vector<int> path; // 0節(jié)點(diǎn)到終點(diǎn)的路徑
// x:目前遍歷的節(jié)點(diǎn)
// graph:存當(dāng)前的圖
void dfs (vector<vector<int>>& graph, int x) 
  1. 確認(rèn)終止條件

什么時(shí)候我們就找到一條路徑了?

當(dāng)目前遍歷的節(jié)點(diǎn) 為 最后一個(gè)節(jié)點(diǎn)的時(shí)候,就找到了一條,從 出發(fā)點(diǎn)到終止點(diǎn)的路徑。

當(dāng)前遍歷的節(jié)點(diǎn),我們定義為x,最后一點(diǎn)節(jié)點(diǎn),就是 graph.size() - 1。

所以 但 x 等于 graph.size() - 1 的時(shí)候就找到一條有效路徑。代碼如下:

// 要求從節(jié)點(diǎn) 0 到節(jié)點(diǎn) n-1 的路徑并輸出,所以是 graph.size() - 1
if (x == graph.size() - 1) { // 找到符合條件的一條路徑
    result.push_back(path); // 收集有效路徑
    return;
}
  1. 處理目前搜索節(jié)點(diǎn)出發(fā)的路徑

接下來(lái)是走 當(dāng)前遍歷節(jié)點(diǎn)x的下一個(gè)節(jié)點(diǎn)。

首先是要找到 x節(jié)點(diǎn)鏈接了哪些節(jié)點(diǎn)呢? 遍歷方式是這樣的:

for (int i = 0; i < graph[x].size(); i++) { // 遍歷節(jié)點(diǎn)n鏈接的所有節(jié)點(diǎn)

接下來(lái)就是將 選中的x所連接的節(jié)點(diǎn),加入到 單一路勁來(lái)。

path.push_back(graph[x][i]); // 遍歷到的節(jié)點(diǎn)加入到路徑中來(lái)

一些錄友可以疑惑這里如果找到x 鏈接的節(jié)點(diǎn)的,例如如果x目前是節(jié)點(diǎn)0,那么目前的過(guò)程就是這樣的:

圖片

二維數(shù)組中,graph[x][i] 都是x鏈接的節(jié)點(diǎn),當(dāng)前遍歷的節(jié)點(diǎn)就是 graph[x][i]

進(jìn)入下一層遞歸

dfs(graph, graph[x][i]); // 進(jìn)入下一層遞歸

最后就是回溯的過(guò)程,撤銷本次添加節(jié)點(diǎn)的操作。 該過(guò)程整體代碼:

for (int i = 0; i < graph[x].size(); i++) { // 遍歷節(jié)點(diǎn)n鏈接的所有節(jié)點(diǎn)
    path.push_back(graph[x][i]); // 遍歷到的節(jié)點(diǎn)加入到路徑中來(lái)
    dfs(graph, graph[x][i]); // 進(jìn)入下一層遞歸
    path.pop_back(); // 回溯,撤銷本節(jié)點(diǎn)
}

本題整體代碼如下:

class Solution {
private:
    vector<vector<int>> result; // 收集符合條件的路徑
    vector<int> path; // 0節(jié)點(diǎn)到終點(diǎn)的路徑
    // x:目前遍歷的節(jié)點(diǎn)
    // graph:存當(dāng)前的圖
    void dfs (vector<vector<int>>& graph, int x) {
        // 要求從節(jié)點(diǎn) 0 到節(jié)點(diǎn) n-1 的路徑并輸出,所以是 graph.size() - 1
        if (x == graph.size() - 1) { // 找到符合條件的一條路徑
            result.push_back(path);
            return;
        }
        for (int i = 0; i < graph[x].size(); i++) { // 遍歷節(jié)點(diǎn)n鏈接的所有節(jié)點(diǎn)
            path.push_back(graph[x][i]); // 遍歷到的節(jié)點(diǎn)加入到路徑中來(lái)
            dfs(graph, graph[x][i]); // 進(jìn)入下一層遞歸
            path.pop_back(); // 回溯,撤銷本節(jié)點(diǎn)
        }
    }
public:
    vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
        path.push_back(0); // 無(wú)論什么路徑已經(jīng)是從0節(jié)點(diǎn)出發(fā)
        dfs(graph, 0); // 開(kāi)始遍歷
        return result;
    }
};

總結(jié)

本題是比較基礎(chǔ)的深度優(yōu)先搜索模板題,這種有向圖路徑問(wèn)題,最合適使用深搜,當(dāng)然本題也可以使用廣搜,但廣搜相對(duì)來(lái)說(shuō)就麻煩了一些,需要記錄一下路徑。

而深搜和廣搜都適合解決顏色類的問(wèn)題,例如島嶼系列,其實(shí)都是 遍歷+標(biāo)記,所以使用哪種遍歷都是可以的。

至于廣搜理論基礎(chǔ),我們?cè)谙乱黄诤煤弥v解,敬請(qǐng)期待!

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多