LeetCode 2867. Count Valid Paths in a Tree Solution in Java, C++, Python & More | Explanation + Code

CoderIndeed
0
2867. Count Valid Paths in a Tree

Description

There is an undirected tree with n nodes labeled from 1 to n. You are given the integer n and a 2D integer array edges of length n - 1, where edges[i] = [ui, vi] indicates that there is an edge between nodes ui and vi in the tree.

Return the number of valid paths in the tree.

A path (a, b) is valid if there exists exactly one prime number among the node labels in the path from a to b.

Note that:

  • The path (a, b) is a sequence of distinct nodes starting with node a and ending with node b such that every two adjacent nodes in the sequence share an edge in the tree.
  • Path (a, b) and path (b, a) are considered the same and counted only once.

 

Example 1:

Input: n = 5, edges = [[1,2],[1,3],[2,4],[2,5]]
Output: 4
Explanation: The pairs with exactly one prime number on the path between them are: 
- (1, 2) since the path from 1 to 2 contains prime number 2. 
- (1, 3) since the path from 1 to 3 contains prime number 3.
- (1, 4) since the path from 1 to 4 contains prime number 2.
- (2, 4) since the path from 2 to 4 contains prime number 2.
It can be shown that there are only 4 valid paths.

Example 2:

Input: n = 6, edges = [[1,2],[1,3],[2,4],[3,5],[3,6]]
Output: 6
Explanation: The pairs with exactly one prime number on the path between them are: 
- (1, 2) since the path from 1 to 2 contains prime number 2.
- (1, 3) since the path from 1 to 3 contains prime number 3.
- (1, 4) since the path from 1 to 4 contains prime number 2.
- (1, 6) since the path from 1 to 6 contains prime number 3.
- (2, 4) since the path from 2 to 4 contains prime number 2.
- (3, 6) since the path from 3 to 6 contains prime number 3.
It can be shown that there are only 6 valid paths.

 

Constraints:

  • 1 <= n <= 105
  • edges.length == n - 1
  • edges[i].length == 2
  • 1 <= ui, vi <= n
  • The input is generated such that edges represent a valid tree.

Solutions

Solution 1: Preprocessing + Union-Find + Enumeration

We can preprocess to get all the prime numbers in [1, n], where prime[i] indicates whether i is a prime number.

Next, we build a graph g based on the two-dimensional integer array, where g[i] represents all the neighbor nodes of node i. If both nodes of an edge are not prime numbers, we merge these two nodes into the same connected component.

Then, we enumerate all prime numbers i in the range of [1, n], considering all paths that include i.

Since i is already a prime number, if i is an endpoint of the path, we only need to accumulate the sizes of all connected components adjacent to node i. If i is a middle point on the path, we need to accumulate the product of the sizes of any two adjacent connected components.

The time complexity is O(n × Î±(n)), and the space complexity is O(n). Here, n is the number of nodes, and α is the inverse function of the Ackermann function.

PythonJavaC++GoTypeScript
class UnionFind: def __init__(self, n): self.p = list(range(n)) self.size = [1] * n def find(self, x): if self.p[x] != x: self.p[x] = self.find(self.p[x]) return self.p[x] def union(self, a, b): pa, pb = self.find(a), self.find(b) if pa == pb: return False if self.size[pa] > self.size[pb]: self.p[pb] = pa self.size[pa] += self.size[pb] else: self.p[pa] = pb self.size[pb] += self.size[pa] return True mx = 10**5 + 10 prime = [True] * (mx + 1) prime[0] = prime[1] = False for i in range(2, mx + 1): if prime[i]: for j in range(i * i, mx + 1, i): prime[j] = False class Solution: def countPaths(self, n: int, edges: List[List[int]]) -> int: g = [[] for _ in range(n + 1)] uf = UnionFind(n + 1) for u, v in edges: g[u].append(v) g[v].append(u) if prime[u] + prime[v] == 0: uf.union(u, v) ans = 0 for i in range(1, n + 1): if prime[i]: t = 0 for j in g[i]: if not prime[j]: cnt = uf.size[uf.find(j)] ans += cnt ans += t * cnt t += cnt return ans(code-box)

Solution 2

PythonJavaC++
class Solution: def countPaths(self, n: int, edges: List[List[int]]) -> int: def mul(x, y): return x * y def dfs(x, f, con, prime, r): v = [1 - prime[x], prime[x]] for y in con[x]: if y == f: continue p = dfs(y, x, con, prime, r) r[0] += mul(p[0], v[1]) + mul(p[1], v[0]) if prime[x]: v[1] += p[0] else: v[0] += p[0] v[1] += p[1] return v prime = [True] * (n + 1) prime[1] = False all_primes = [] for i in range(2, n + 1): if prime[i]: all_primes.append(i) for x in all_primes: temp = i * x if temp > n: break prime[temp] = False if i % x == 0: break con = [[] for _ in range(n + 1)] for e in edges: con[e[0]].append(e[1]) con[e[1]].append(e[0]) r = [0] dfs(1, 0, con, prime, r) return r[0](code-box)

Post a Comment

0Comments

Post a Comment (0)

#buttons=(Accept !) #days=(20)

Our website uses cookies to enhance your experience. Check Now
Accept !