-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLinkedListInBinaryTree_Day58.py
More file actions
86 lines (69 loc) · 2.55 KB
/
Copy pathLinkedListInBinaryTree_Day58.py
File metadata and controls
86 lines (69 loc) · 2.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# Brute Approach
class Solution:
def isSubPath(self, head: Optional[ListNode], root: Optional[TreeNode]) -> bool:
if not root:
return False
def dfs(list_node, tree_node):
if not list_node: # reached end of list
return True
if not tree_node: # tree ended first
return False
if list_node.val != tree_node.val:
return False
return dfs(list_node.next, tree_node.left) or dfs(list_node.next, tree_node.right)
return dfs(head, root) or self.isSubPath(head, root.left) or self.isSubPath(head, root.right)
#Better Approach
class Solution:
def isSubPath(self, head: Optional[ListNode], root: Optional[TreeNode]) -> bool:
if not root:
return False
def dfs(list_node, tree_node):
if not list_node:
return True
if not tree_node:
return False
if list_node.val != tree_node.val:
return False
return dfs(list_node.next, tree_node.left) or dfs(list_node.next, tree_node.right)
# Only check when values match
if head.val == root.val and dfs(head, root):
return True
return self.isSubPath(head, root.left) or self.isSubPath(head, root.right)
#Optimal Approach
class Solution:
def isSubPath(self, head: Optional[ListNode], root: Optional[TreeNode]) -> bool:
# Convert linked list to array (pattern)
pattern = []
while head:
pattern.append(head.val)
head = head.next
# Build prefix table (KMP failure function)
lps = [0] * len(pattern)
j = 0
for i in range(1, len(pattern)):
while j > 0 and pattern[i] != pattern[j]:
j = lps[j - 1]
if pattern[i] == pattern[j]:
j += 1
lps[i] = j
# DFS on tree with pattern matching
def dfs(node, j):
if not node:
return False
while j > 0 and node.val != pattern[j]:
j = lps[j - 1]
if node.val == pattern[j]:
j += 1
if j == len(pattern):
return True
return dfs(node.left, j) or dfs(node.right, j)
return dfs(root, 0)
# Time Complexity:
# Convert list → O(M)
# Build prefix table → O(M)
# DFS tree traversal → O(N) (each node visited once, with KMP rollback).
# Total → O(N + M)
# Space Complexity:
# Prefix table = O(M)
# Recursion stack = O(H)
# Total = O(M + H)