3910. Count Connected Subgraphs with Even Node Sum
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
sis connected (every node inscan reach every other node insusing only the kept edges). - The sum of the node values in
sis 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 nodesiin the subset; this sum must be divisible by2.
Both conditions must hold at the same time for a subset to be counted.
How We Pick the Algorithm
Why Simulation / Basic DSA?
This problem maps to Simulation / Basic DSA through a short path in the full flowchart.
Following the described process directly produces the answer.
Open in FlowchartShow 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
nnodes and a list ofedgesconnecting 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 - 1edges, 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 all2ⁿ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 nodeiwhose bit is set insub. 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)), wherenis the number of nodes andeis the number of edges. We enumerate2ⁿsubsets, and for each one we spendO(n)computing the value sum plusO(n + e)running the DFS. - Space Complexity:
O(n + e)for the adjacency list, plusO(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 tog[0], add 0 tog[1] - Edge
[1, 2]: add 2 tog[1], add 1 tog[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 s | Value sum | Even? | vis = m ^ sub | DFS start | DFS result vis | vis == m? | Counted? |
|---|---|---|---|---|---|---|---|---|
001 | {0} | 1 | No | — | — | — | — | ✗ |
010 | {1} | 0 | Yes | 101 | node 1 | 111 | Yes | ✓ |
011 | {0,1} | 1 | No | — | — | — | — | ✗ |
100 | {2} | 1 | No | — | — | — | — | ✗ |
101 | {0,2} | 2 | Yes | 010 | node 2 | 110 | No | ✗ |
110 | {1,2} | 1 | No | — | — | — | — | ✗ |
111 | {0,1,2} | 2 | Yes | 000 | node 2 | 111 | Yes | ✓ |
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 atg[2] = [1], but node 1 is already "visited" (it's outside the subset). DFS stops. - Final
vis = 110 ≠ 111→ not 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 == m→ connected. 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)
681class 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}
731class 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};
661/**
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}
75Time and Space Complexity
-
Time complexity:
O(2^n × (n + m)), wherenis the number of nodes andmis the number of edges. The outer loop iterates over all2^n - 1non-empty subsets of nodes. For each subset, computing the sumstakesO(n)time, and thedfstraversal visits each node and explores each edge in the worst case, costingO(n + m). Thus the total time isO(2^n × (n + m)). -
Space complexity:
O(n + m). The adjacency listgstores all nodes and edges, requiringO(n + m)space. The recursion stack ofdfscan go as deep asO(n)in the worst case. Combined, the space complexity isO(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 RoadmapWhat'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
271private 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}
301const 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}
30Recommended Readings
https assets algo monster cover_photos dfs svg Depth First Search Prereqs Recursion Review problems recursion_intro Trees problems tree_intro With a solid understanding of recursion under our belts we are now ready to tackle one of the most useful techniques in coding interviews Depth First Search DFS As the name suggests
https assets algo monster cover_photos bfs svg Breadth First Search on Trees Hopefully by this time you've drunk enough DFS Kool Aid to understand its immense power and seen enough visualization to create a call stack in your mind Now let me introduce the companion spell Breadth First Search BFS
Union Find Disjoint Set Union Data Structure Introduction Prerequisite Depth First Search Review problems dfs_intro So far in our DFS discussions we have mostly dealt with graphs with all the nodes connected to each other and thus forming one connected component Let's now look at a more general case where
Want a Structured Path to Master System Design Too? Don’t Miss This!