Facebook Pixel

3910. Count Connected Subgraphs with Even Node Sum

LeetCode ↗

Problem Description

You are given an undirected graph with n nodes labeled from 0 to n - 1. Node i has a value of nums[i], which is either 0 or 1. The edges of the graph are given by a 2D array edges, where edges[i] = [uᵢ, vᵢ] represents an edge between node uᵢ and node vᵢ.

For a non-empty subset s of nodes in the graph, we build its induced subgraph as follows:

  • Keep only the nodes that belong to s.
  • Keep only the edges whose two endpoints are both in s.

Your task is to count how many non-empty subsets s of nodes satisfy both of the following conditions:

  • The induced subgraph of s is connected (every node in s can reach every other node in s using only the kept edges).
  • The sum of the node values in s is even.

Return an integer representing the number of such subsets.

Example walkthrough of the conditions:

  • A subset is connected if, starting from any single node in the subset, you can reach all other nodes in the subset by traveling along edges that stay inside the subset.
  • The value sum is simply nums[i] added up over all nodes i in the subset; this sum must be divisible by 2.

Both conditions must hold at the same time for a subset to be counted.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

How We Pick the Algorithm

Why Simulation / Basic DSA?

This problem maps to Simulation / Basic DSA through a short path in the full flowchart.

DirecttransformationoryesNeedoptimizedgraphnoSimulation /Basic DSA

Following the described process directly produces the answer.

Open in Flowchart
Show step-by-step reasoning

First, let's pin down the algorithm using the Flowchart. Here's a step-by-step walkthrough:

Is it a graph?

  • Yes: The problem explicitly gives us n nodes and a list of edges connecting them, forming an undirected graph.

Is it a tree?

  • No: The graph can contain cycles and is not guaranteed to be acyclic or have exactly n - 1 edges, so it is a general graph, not a tree.

Is the problem related to directed acyclic graphs?

  • No: The graph is undirected, so it is not a directed acyclic graph.

Is the problem related to shortest paths?

  • No: We are not measuring distances or finding shortest routes between nodes; we only care about whether subsets form connected induced subgraphs.

Does the problem involve connectivity?

  • Yes: The core requirement is checking whether the induced subgraph of a chosen subset of nodes is connected.

Does the problem have small constraints?

  • Yes: The number of nodes does not exceed 13, which allows us to enumerate all 2ⁿ subsets of nodes within the limits.

DFS/backtracking?

  • Yes: For each enumerated subset, we run a Depth-First Search starting from one node in the subset to verify that all nodes in the subset are reachable, confirming connectivity.

Conclusion: The flowchart leads us to enumerate all node subsets and apply the Depth-First Search pattern to check the connectivity of each induced subgraph, counting those whose node value sum is even.

Intuition

The first thing to notice is the size limit: the number of nodes n is very small (no more than 13). Whenever we see such tiny constraints, it is a strong hint that we can afford to enumerate every possible subset of nodes. With n nodes, there are 2ⁿ subsets in total, and since 2¹³ = 8192, looping over all of them is completely feasible.

So the plan becomes: go through each non-empty subset s, and for each one, directly check whether it satisfies the two required conditions.

To represent a subset compactly, we use a bitmask — an integer where the i-th bit being 1 means node i is included in the subset. This lets us loop sub from 1 to 2ⁿ - 1 and treat each value as one candidate subset.

For each subset, the two conditions are checked separately:

  • Even value sum: We add up nums[i] for every node i whose bit is set in sub. If this sum is odd, the subset fails immediately and we skip it. This is a cheap test, so it's worth doing first to avoid extra work.

  • Connectivity: This is where Depth-First Search comes in. A subset's induced subgraph is connected if, starting from any one node in the subset, we can reach all other nodes in the subset using only edges whose both endpoints lie inside the subset. So we pick one node from sub (for example, the lowest set bit), run a DFS, and see if it touches every node in the subset.

The clever trick for the DFS is how we track visited nodes. Instead of resetting a fresh visited array each time, we initialize a vis mask so that all nodes not in the subset are already marked as visited (vis = m ^ sub). This automatically prevents the DFS from wandering into nodes outside s, because those nodes look "already visited." Then we start DFS from a node inside the subset, marking each reachable node as visited.

After the DFS finishes, if every bit of vis is set (vis == m), it means the DFS reached all nodes in the subset plus the already-marked outside nodes — confirming the induced subgraph is fully connected. In that case we count this subset toward the answer.

By combining subset enumeration with a DFS connectivity check and an even-sum filter, we naturally arrive at the complete solution.

Pattern Learn more about Depth-First Search, Breadth-First Search, Union Find and Graph patterns.

Solution Approach

We use Bitmask Enumeration combined with DFS to solve the problem. Here's how the implementation works step by step.

Step 1: Build the adjacency list

First, we build the graph from the edges array. Since the graph is undirected, for each edge [u, v] we add v to the adjacency list of u and u to the adjacency list of v:

n = len(nums)
g = [[] for _ in range(n)]
for u, v in edges:
    g[u].append(v)
    g[v].append(u)

Step 2: Enumerate all non-empty subsets

We define m = (1 << n) - 1, which is a bitmask with all n bits set to 1 (representing the full set of nodes). Then we loop sub from 1 to m, where each value of sub represents one non-empty subset of nodes. The i-th bit of sub being 1 means node i is in the subset:

m = (1 << n) - 1
ans = 0
for sub in range(1, m + 1):
    ...

Step 3: Check the even-sum condition

For each subset, we compute the sum of node values by iterating over all nodes and adding nums[i] whenever the i-th bit of sub is set. If the sum is odd, we skip this subset right away, since it cannot satisfy the requirement:

s = sum(x for i, x in enumerate(nums) if sub >> i & 1)
if s % 2:
    continue

Step 4: Set up the visited mask for DFS

We use an integer vis to track visited nodes. The key trick is to initialize vis = m ^ sub, which marks all nodes outside the subset as already visited. This way, the DFS will never step into nodes that are not part of s, because they appear "visited":

vis = m ^ sub

Step 5: Run DFS to check connectivity

We start the DFS from one node inside the subset. A convenient choice is the highest set bit, obtained via sub.bit_length() - 1. The DFS marks the current node as visited in vis, then recursively visits all unvisited neighbors:

def dfs(u: int) -> None:
    nonlocal vis
    vis |= 1 << u
    for v in g[u]:
        if (vis >> v & 1) == 0:
            dfs(v)

dfs(sub.bit_length() - 1)

Step 6: Verify full connectivity and count

After the DFS finishes, if every bit in vis is set (vis == m), it means the DFS reached every node in the subset (the outside nodes were already pre-marked). This confirms the induced subgraph is connected, so we increment the answer:

if vis == m:
    ans += 1

Complexity Analysis

  • Time Complexity: O(2ⁿ × (n + e)), where n is the number of nodes and e is the number of edges. We enumerate 2ⁿ subsets, and for each one we spend O(n) computing the value sum plus O(n + e) running the DFS.
  • Space Complexity: O(n + e) for the adjacency list, plus O(n) for the DFS recursion stack.

Since n ≤ 13, the total number of subsets stays small enough for this brute-force enumeration to run efficiently.

Example Walkthrough

Let's trace through the solution approach using a small, concrete example.

Input:

  • nums = [1, 0, 1] (node 0 has value 1, node 1 has value 0, node 2 has value 1)
  • edges = [[0, 1], [1, 2]]

This gives us a simple "path" graph: 0 — 1 — 2.


Step 1: Build the adjacency list

Processing each edge:

  • Edge [0, 1]: add 1 to g[0], add 0 to g[1]
  • Edge [1, 2]: add 2 to g[1], add 1 to g[2]

Result:

g[0] = [1]
g[1] = [0, 2]
g[2] = [1]

Step 2: Set up the enumeration range

With n = 3, we have m = (1 << 3) - 1 = 7 (binary 111). We loop sub from 1 to 7, where each value is a candidate subset.


Steps 3–6: Process each subset

For each sub, we first check the even-sum condition, then (if it passes) run DFS for connectivity. Recall dfs starts from the highest set bit and uses vis = m ^ sub to fence off outside nodes.

sub (binary)Nodes in sValue sumEven?vis = m ^ subDFS startDFS result visvis == m?Counted?
001{0}1No
010{1}0Yes101node 1111Yes
011{0,1}1No
100{2}1No
101{0,2}2Yes010node 2110No
110{1,2}1No
111{0,1,2}2Yes000node 2111Yes

Detailed look at the interesting cases:

Case sub = 101 (nodes {0, 2}):

  • Value sum = nums[0] + nums[2] = 1 + 1 = 2, which is even → passes the filter.
  • vis = 7 ^ 5 = 010 (binary), so node 1 is pre-marked as visited.
  • DFS starts at the highest set bit: 5.bit_length() - 1 = 2, so start at node 2.
  • Visit node 2 → vis = 110. Look at g[2] = [1], but node 1 is already "visited" (it's outside the subset). DFS stops.
  • Final vis = 110 ≠ 111not connected. This makes sense: nodes 0 and 2 have no direct edge, and node 1 (the bridge) isn't in the subset.

Case sub = 111 (nodes {0, 1, 2}):

  • Value sum = 1 + 0 + 1 = 2, even → passes.
  • vis = 7 ^ 7 = 000, nothing pre-marked.
  • DFS starts at node 2: visit 2 → vis = 100. Neighbor 1 unvisited → visit 1 → vis = 110. From 1, neighbor 0 unvisited → visit 0 → vis = 111. Neighbor 2 already visited.
  • Final vis = 111 == mconnected. Counted.

Final Result:

Two subsets satisfy both conditions: {1} and {0, 1, 2}. The answer is 2.

This walkthrough shows how the even-sum filter quickly discards 4 of the 7 subsets cheaply, and how the vis = m ^ sub trick lets a single DFS confirm connectivity without ever wandering outside the chosen subset.

Solution Implementation

1from typing import List
2
3
4class Solution:
5    def evenSumSubgraphs(self, nums: List[int], edges: List[List[int]]) -> int:
6        num_nodes = len(nums)
7
8        # Build adjacency list of the undirected graph.
9        adjacency: List[List[int]] = [[] for _ in range(num_nodes)]
10        for u, v in edges:
11            adjacency[u].append(v)
12            adjacency[v].append(u)
13
14        full_mask = (1 << num_nodes) - 1
15        answer = 0
16
17        # Enumerate every non-empty subset of nodes as a bitmask.
18        for subset in range(1, full_mask + 1):
19            # Sum of node values that belong to the current subset.
20            subset_sum = sum(
21                value for index, value in enumerate(nums) if subset >> index & 1
22            )
23
24            # Only even-sum subsets are candidates.
25            if subset_sum % 2:
26                continue
27
28            # Mark nodes outside the subset as already "visited" so the DFS
29            # can only walk through nodes that belong to the subset.
30            visited = full_mask ^ subset
31
32            def dfs(node: int) -> None:
33                nonlocal visited
34                # Mark the current node as visited.
35                visited |= 1 << node
36                for neighbor in adjacency[node]:
37                    # Visit only unvisited neighbors (i.e. unvisited subset nodes).
38                    if (visited >> neighbor & 1) == 0:
39                        dfs(neighbor)
40
41            # Start the DFS from the highest-indexed node in the subset.
42            dfs(subset.bit_length() - 1)
43
44            # If every bit is set, every subset node was reachable from the
45            # start node, meaning the subset induces a connected subgraph.
46            if visited == full_mask:
47                answer += 1
48
49        return answer
50```
51
52**Notes on the approach:**
53
54- **Time complexity:** `O(2^n · (n + E))` — for each of the `2^n` subsets we compute a sum and run a DFS. This is exponential, suitable only for small `n` (typically `n ≤ 20` or less given recursion depth).
55- **Space complexity:** `O(n + E)` for the graph, plus recursion stack up to `O(n)`.
56
57**Alternative perspective:** If `n` is moderately large, the recursive `dfs` could hit Python's recursion limit; an iterative DFS using an explicit stack would be safer:
58
59```python3
60stack = [subset.bit_length() - 1]
61visited |= 1 << stack[0]
62while stack:
63    node = stack.pop()
64    for neighbor in adjacency[node]:
65        if (visited >> neighbor & 1) == 0:
66            visited |= 1 << neighbor
67            stack.append(neighbor)
68
1class Solution {
2    // Bitmask tracking visited nodes during the connectivity DFS
3    private int visited;
4    // Full bitmask representing all n nodes (n bits set to 1)
5    private int fullMask;
6    // Adjacency list of the graph
7    private List<Integer>[] graph;
8
9    /**
10     * Counts the number of connected subgraphs (non-empty node subsets that form
11     * a single connected component) whose total node-value sum is even.
12     */
13    public int evenSumSubgraphs(int[] nums, int[][] edges) {
14        int n = nums.length;
15
16        // Build the undirected adjacency list
17        graph = new List[n];
18        Arrays.setAll(graph, k -> new ArrayList<>());
19        for (int[] edge : edges) {
20            graph[edge[0]].add(edge[1]);
21            graph[edge[1]].add(edge[0]);
22        }
23
24        // fullMask has the lowest n bits set, representing every node
25        fullMask = (1 << n) - 1;
26
27        int ans = 0;
28        // Enumerate every non-empty subset of nodes as a bitmask
29        for (int subset = 1; subset <= fullMask; subset++) {
30            // Compute the sum of node values included in this subset
31            int sum = 0;
32            for (int i = 0; i < n; i++) {
33                if (((subset >> i) & 1) == 1) {
34                    sum += nums[i];
35                }
36            }
37
38            // Skip subsets whose sum is odd
39            if (sum % 2 != 0) {
40                continue;
41            }
42
43            // Mark all nodes NOT in the subset as already visited, so the DFS
44            // is confined to nodes within the current subset
45            visited = fullMask ^ subset;
46
47            // Start the DFS from the lowest-index node present in the subset
48            dfs(Integer.numberOfTrailingZeros(subset));
49
50            // If every node is now marked visited, the subset is fully connected
51            if (visited == fullMask) {
52                ans++;
53            }
54        }
55        return ans;
56    }
57
58    /**
59     * Depth-first search that marks node u and all reachable unvisited
60     * neighbours (limited to the current subset) as visited.
61     */
62    private void dfs(int u) {
63        // Mark the current node as visited
64        visited |= 1 << u;
65        // Visit every adjacent node that has not been visited yet
66        for (int v : graph[u]) {
67            if (((visited >> v) & 1) == 0) {
68                dfs(v);
69            }
70        }
71    }
72}
73
1class Solution {
2public:
3    int evenSumSubgraphs(vector<int>& nums, vector<vector<int>>& edges) {
4        int n = nums.size();
5
6        // Build the adjacency list representation of the graph
7        vector<vector<int>> graph(n);
8        for (auto& edge : edges) {
9            graph[edge[0]].push_back(edge[1]);
10            graph[edge[1]].push_back(edge[0]);
11        }
12
13        // fullMask represents the bitmask where all n nodes are set
14        int fullMask = (1 << n) - 1;
15        int answer = 0;
16
17        // visited is a bitmask tracking which nodes have been reached during DFS
18        int visited;
19
20        // DFS marks every node reachable from u (within the current subset).
21        // Nodes outside the subset are pre-marked as visited so we never enter them.
22        auto dfs = [&](this auto dfs, int u) -> void {
23            visited |= 1 << u; // Mark the current node as visited
24            for (int next : graph[u]) {
25                // Only traverse into nodes that have not been visited yet
26                if (((visited >> next) & 1) == 0) {
27                    dfs(next);
28                }
29            }
30        };
31
32        // Enumerate every non-empty subset of nodes
33        for (int subset = 1; subset <= fullMask; subset++) {
34            // Compute the sum of node values contained in this subset
35            int sum = 0;
36            for (int i = 0; i < n; i++) {
37                if ((subset >> i) & 1) {
38                    sum += nums[i];
39                }
40            }
41
42            // Skip subsets whose total sum is odd
43            if (sum % 2 != 0) {
44                continue;
45            }
46
47            // Pre-mark all nodes NOT in the subset as visited,
48            // so the DFS stays strictly inside the subset.
49            visited = fullMask ^ subset;
50
51            // Start DFS from the highest-index node present in the subset.
52            // 31 - __builtin_clz(subset) gives the position of the most
53            // significant set bit, i.e. one valid starting node.
54            dfs(31 - __builtin_clz(subset));
55
56            // If after the DFS every node is visited, then all nodes inside
57            // the subset were reachable from the start => the subset is connected.
58            if (visited == fullMask) {
59                answer++;
60            }
61        }
62
63        return answer;
64    }
65};
66
1/**
2 * Counts the number of non-empty connected subgraphs (vertex subsets that are
3 * connected in the induced subgraph) whose total node-value sum is even.
4 *
5 * @param nums  - Value assigned to each node, indexed 0..n-1.
6 * @param edges - Undirected edges as [u, v] pairs.
7 * @returns The count of valid connected subsets with an even value sum.
8 */
9function evenSumSubgraphs(nums: number[], edges: number[][]): number {
10    const n: number = nums.length;
11
12    // Build adjacency list for the undirected graph.
13    const graph: number[][] = Array.from({ length: n }, () => []);
14    for (const [u, v] of edges) {
15        graph[u].push(v);
16        graph[v].push(u);
17    }
18
19    // Full bitmask representing all n nodes being present/visited.
20    const fullMask: number = (1 << n) - 1;
21
22    let answer: number = 0;
23    let visited: number = 0; // Bitmask of visited nodes during a DFS run.
24
25    /**
26     * Depth-first search starting from node `start`.
27     * Only traverses nodes that are part of the current subset, because nodes
28     * outside the subset are pre-marked as visited before the call.
29     *
30     * @param start - The node index to begin traversal from.
31     */
32    const dfs = (start: number): void => {
33        visited |= 1 << start; // Mark current node as visited.
34        for (const next of graph[start]) {
35            // Visit each unvisited neighbor (neighbors outside the subset are
36            // already marked, so they are skipped automatically).
37            if (((visited >> next) & 1) === 0) {
38                dfs(next);
39            }
40        }
41    };
42
43    // Enumerate every non-empty subset of the n nodes.
44    for (let subset = 1; subset <= fullMask; subset++) {
45        // Compute the sum of node values contained in this subset.
46        let sum: number = 0;
47        for (let i = 0; i < n; i++) {
48            if ((subset >> i) & 1) {
49                sum += nums[i];
50            }
51        }
52
53        // Skip subsets whose total value sum is odd.
54        if (sum % 2 !== 0) {
55            continue;
56        }
57
58        // Pre-mark all nodes NOT in the subset as visited, so the DFS is
59        // confined to the induced subgraph of `subset`.
60        visited = fullMask ^ subset;
61
62        // Pick the lowest set bit of `subset` as the DFS starting node.
63        const startNode: number = subset & -subset;
64        dfs(Math.log2(startNode));
65
66        // If every node became visited, the subset's induced subgraph is
67        // connected (all subset nodes were reachable from the start node).
68        if (visited === fullMask) {
69            answer++;
70        }
71    }
72
73    return answer;
74}
75

Time and Space Complexity

  • Time complexity: O(2^n × (n + m)), where n is the number of nodes and m is the number of edges. The outer loop iterates over all 2^n - 1 non-empty subsets of nodes. For each subset, computing the sum s takes O(n) time, and the dfs traversal visits each node and explores each edge in the worst case, costing O(n + m). Thus the total time is O(2^n × (n + m)).

  • Space complexity: O(n + m). The adjacency list g stores all nodes and edges, requiring O(n + m) space. The recursion stack of dfs can go as deep as O(n) in the worst case. Combined, the space complexity is O(n + m).

Pattern Learn more about how to find time and space complexity quickly.

Common Pitfalls

Pitfall: Defining the recursive dfs closure inside the subset loop

The most subtle issue with this implementation is that the dfs function is redefined on every iteration of the 2^n subset loop. While this works correctly, it carries two hidden costs and one real correctness risk.

1. Performance overhead from repeated function creation

Each iteration creates a brand-new closure object that captures nonlocal visited and references adjacency. With n = 13, that's up to 8192 function definitions. The redefinition itself is cheap, but combined with Python's recursive call overhead, it makes the constant factor noticeably worse than necessary.

Solution: Define the DFS once outside the loop and pass visited through explicitly (or return it), avoiding the closure rebuild:

def dfs(node: int, visited: int) -> int:
    visited |= 1 << node
    for neighbor in adjacency[node]:
        if (visited >> neighbor & 1) == 0:
            visited = dfs(neighbor, visited)
    return visited

for subset in range(1, full_mask + 1):
    subset_sum = sum(v for i, v in enumerate(nums) if subset >> i & 1)
    if subset_sum % 2:
        continue
    visited = dfs(subset.bit_length() - 1, full_mask ^ subset)
    if visited == full_mask:
        answer += 1

Pitfall: Recursion depth limit with deep/chain-like graphs

When the subset forms a long path (e.g., 0–1–2–...–n-1), the recursive dfs reaches a depth equal to the subset size. For larger n, or if this pattern is reused on bigger inputs, you may hit Python's default recursion limit (1000) and trigger a RecursionError.

Solution: Use the iterative, stack-based DFS shown in the notes. It eliminates recursion depth concerns entirely:

visited = full_mask ^ subset
start = subset.bit_length() - 1
stack = [start]
visited |= 1 << start
while stack:
    node = stack.pop()
    for neighbor in adjacency[node]:
        if (visited >> neighbor & 1) == 0:
            visited |= 1 << neighbor
            stack.append(neighbor)

Pitfall: Forgetting that the empty subset is excluded

The loop starts at subset = 1, intentionally skipping subset = 0. If you accidentally start from 0, the empty set has sum 0 (even) and subset.bit_length() - 1 evaluates to -1, which Python interprets as the last node — corrupting the DFS and the count.

Solution: Always begin enumeration at 1 and never call dfs on an empty subset. The guard is implicit in range(1, full_mask + 1); keep it intact.


Pitfall: Choosing an arbitrary DFS start node not in the subset

The start node is computed as subset.bit_length() - 1, which is guaranteed to be a set bit (the highest one). A tempting but incorrect alternative is to hardcode the start as node 0 or pick subset & -subset without converting it to an index. If node 0 is not in the subset, starting there would mark an outside node and produce wrong connectivity results.

Solution: Always derive the start node from a bit that is actually present in subset. Both subset.bit_length() - 1 (highest set bit) and (subset & -subset).bit_length() - 1 (lowest set bit) are valid choices.


Pitfall: Recomputing the subset sum from scratch every iteration

Computing subset_sum with an O(n) generator on each of the 2^n subsets adds a full factor of n to the runtime. For n ≤ 13 this is acceptable, but it is avoidable.

Solution: Use the incremental relation between a subset and its lowest set bit. Precompute sums in an array so each lookup is O(1):

subset_sum = [0] * (1 << num_nodes)
for subset in range(1, 1 << num_nodes):
    low = subset & -subset
    idx = low.bit_length() - 1
    subset_sum[subset] = subset_sum[subset ^ low] + nums[idx]

This reduces the per-subset sum cost from O(n) to O(1), trimming the overall complexity to O(2ⁿ · (n + E)) dominated solely by the DFS.

Ready to land your dream job?

Unlock your dream job with a 5-minute quiz for a personalized study roadmap!

Get My Roadmap
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Get a Personalized Study Roadmap:

What's the output of running the following function using input 56?

1KEYBOARD = {
2    '2': 'abc',
3    '3': 'def',
4    '4': 'ghi',
5    '5': 'jkl',
6    '6': 'mno',
7    '7': 'pqrs',
8    '8': 'tuv',
9    '9': 'wxyz',
10}
11
12def letter_combinations_of_phone_number(digits):
13    def dfs(path, res):
14        if len(path) == len(digits):
15            res.append(''.join(path))
16            return
17
18        next_number = digits[len(path)]
19        for letter in KEYBOARD[next_number]:
20            path.append(letter)
21            dfs(path, res)
22            path.pop()
23
24    res = []
25    dfs([], res)
26    return res
27
1private static final Map<Character, char[]> KEYBOARD = Map.of(
2    '2', "abc".toCharArray(),
3    '3', "def".toCharArray(),
4    '4', "ghi".toCharArray(),
5    '5', "jkl".toCharArray(),
6    '6', "mno".toCharArray(),
7    '7', "pqrs".toCharArray(),
8    '8', "tuv".toCharArray(),
9    '9', "wxyz".toCharArray()
10);
11
12public static List<String> letterCombinationsOfPhoneNumber(String digits) {
13    List<String> res = new ArrayList<>();
14    dfs(new StringBuilder(), res, digits.toCharArray());
15    return res;
16}
17
18private static void dfs(StringBuilder path, List<String> res, char[] digits) {
19    if (path.length() == digits.length) {
20        res.add(path.toString());
21        return;
22    }
23    char next_digit = digits[path.length()];
24    for (char letter : KEYBOARD.get(next_digit)) {
25        path.append(letter);
26        dfs(path, res, digits);
27        path.deleteCharAt(path.length() - 1);
28    }
29}
30
1const KEYBOARD = {
2    '2': 'abc',
3    '3': 'def',
4    '4': 'ghi',
5    '5': 'jkl',
6    '6': 'mno',
7    '7': 'pqrs',
8    '8': 'tuv',
9    '9': 'wxyz',
10}
11
12function letter_combinations_of_phone_number(digits) {
13    let res = [];
14    dfs(digits, [], res);
15    return res;
16}
17
18function dfs(digits, path, res) {
19    if (path.length === digits.length) {
20        res.push(path.join(''));
21        return;
22    }
23    let next_number = digits.charAt(path.length);
24    for (let letter of KEYBOARD[next_number]) {
25        path.push(letter);
26        dfs(digits, path, res);
27        path.pop();
28    }
29}
30

Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More