Fundamentals 8 min read

All Paths From Source to Target (LeetCode 797) – Problem Description, Analysis, and Multi‑Language Solutions

This article presents LeetCode problem 797, which asks for all possible paths from node 0 to node n‑1 in a directed acyclic graph, explains the DFS approach, lists constraints and examples, and provides complete implementations in Java, C++, C, and Python.

IT Services Circle
IT Services Circle
IT Services Circle
All Paths From Source to Target (LeetCode 797) – Problem Description, Analysis, and Multi‑Language Solutions

LeetCode 797 – "All Paths From Source to Target" – asks you to find every possible path from node 0 to node n‑1 in a directed acyclic graph (DAG). The input is an adjacency list graph[i] where each entry lists the nodes reachable directly from node i.

Problem description : Given a DAG with n nodes, output all paths from the source (node 0) to the target (node n‑1). The order of the paths does not matter.

Examples :

Input: graph = [[1,2],[3],[3],[]] → Output: [[0,1,3],[0,2,3]]

Input: graph = [[4,3,1],[3,2,4],[3],[4],[]] → Output: [[0,4],[0,3,4],[0,1,3,4],[0,1,2,3,4],[0,1,4]]

Constraints :

n == graph.length

2 ≤ n ≤ 15

0 ≤ graph[i][j] < n

No self‑loops ( graph[i][j] != i )

All entries in graph[i] are distinct

The input is guaranteed to be a DAG

Problem analysis : Because the graph is acyclic, a depth‑first search (DFS) from node 0 can explore every possible route without risking infinite loops. When the DFS reaches node n‑1, the current traversal path is stored as a valid result. Backtracking (removing the last node from the path) is required after exploring each branch.

Java solution :

public List
> allPathsSourceTarget(int[][] graph) {
    List
> ans = new ArrayList<>();
    List
path = new ArrayList<>();
    path.add(0); // start node
    dfs(graph, 0, ans, path);
    return ans;
}

private void dfs(int[][] graph, int index, List
> ans, List
path) {
    if (index == graph.length - 1) {
        ans.add(new ArrayList<>(path));
        return;
    }
    int[] directs = graph[index];
    for (int i = 0; i < directs.length; i++) {
        path.add(directs[i]); // choose next node
        dfs(graph, directs[i], ans, path);
        path.remove(path.size() - 1); // backtrack
    }
}

C++ solution :

vector
> allPathsSourceTarget(vector
>& graph) {
    vector
> ans;
    vector
path;
    path.push_back(0);
    dfs(graph, 0, ans, path);
    return ans;
}

void dfs(vector
>& graph, int index, vector
>& ans, vector
& path) {
    if (index == graph.size() - 1) {
        ans.emplace_back(path);
        return;
    }
    for (int g : graph[index]) {
        path.emplace_back(g);
        dfs(graph, g, ans, path);
        path.pop_back(); // backtrack
    }
}

C solution (LeetCode style) :

void dfs(int** graph, int graphSize, int* graphColSize, int* returnSize, int** returnColumnSizes, int** ans, int* path, int v, int count) {
    if (v == graphSize - 1) {
        ans[*returnSize] = malloc(count * sizeof(int));
        memcpy(ans[*returnSize], path, count * sizeof(int));
        (*returnColumnSizes)[(*returnSize)++] = count;
        return;
    }
    for (int i = 0; i < graphColSize[v]; ++i) {
        path[count++] = graph[v][i];
        dfs(graph, graphSize, graphColSize, returnSize, returnColumnSizes, ans, path, graph[v][i], count);
        count--;
    }
}

int** allPathsSourceTarget(int** graph, int graphSize, int* graphColSize, int* returnSize, int** returnColumnSizes) {
    int** ans = malloc(20000 * sizeof(int*));
    int* path = malloc(15 * sizeof(int));
    int v = 0, count = 0;
    *returnSize = 0;
    *returnColumnSizes = malloc(20000 * sizeof(int));
    path[count++] = v; // start node
    dfs(graph, graphSize, graphColSize, returnSize, returnColumnSizes, ans, path, v, count);
    return ans;
}

Python solution :

def allPathsSourceTarget(self, graph: List[List[int]]) -> List[List[int]]:
    def dfs(index):
        if index == len(graph) - 1:
            ans.append(path[:])
            return
        for direct in graph[index]:
            path.append(direct)  # choose
            dfs(direct)
            path.pop()          # backtrack
    ans = []
    path = [0]
    dfs(0)
    return ans

All four implementations follow the same DFS‑backtracking strategy, guaranteeing that every source‑to‑target path in the DAG is enumerated.

JavaalgorithmPythonC++LeetCodeDFSgraph
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.