Problem
Given a binary tree root
and a linked list with head
as the first node.
Return True if all the elements in the linked list starting from the head
correspond to some downward path connected in the binary tree otherwise return False.
In this context downward path means a path that starts at some node and goes downwards.
Examples
Example 1:
Input: head = [4,2,8], root = [1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3]
Output: true
Explanation: Nodes in blue form a subpath in the binary Tree.
Example 2:
Input: head = [1,4,2,6], root = [1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3]
Output: true
Example 3:
Input: head = [1,4,2,6,8], root = [1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3]
Output: false
Explanation: There is no path in the binary tree that contains all the elements of the linked list from head.
Similar Problems
Subtree of Another Tree Problem
Solution
Method 1 - Brute Force DFS
To solve this problem using Depth-First Search (DFS), we’ll follow these steps:
- Traverse the Tree:
- We’ll start by traversing the binary tree from every node to find a node that matches the head of the linked list.
- Match Path:
- Once we find a potential starting node in the tree that matches the head of the linked list, we use DFS to check if this node and its descendants match the linked list.
- Recursive Checking:
- We’ll recursively check the left and right children of the current tree node to see if they continue to match the subsequent nodes in the linked list.
- If at any point the values of the linked list node and the tree node do not match, or if we reach the end of the tree path with remaining nodes in the linked list, we backtrack and try another path.
Video Explanation\
Here is the video epxlanation:
Code
Java
class Solution {
public boolean isSubPath(ListNode head, TreeNode root) {
// checking for root here,
// as isSubPath is traversed for both left and right
// can result in NPE otherwise
if (root == null) {
return false;
}
// Path can start from root => dfs
// Otherwise it can exist in left or right side
return dfs(head, root) || isSubPath(head, root.left) || isSubPath(head, root.right);
}
private boolean dfs(ListNode head, TreeNode root) {
if (head == null) {
return true; // Reached end of linked list, so it matches.
}
if (root == null) {
return false; // Reached the end of a path in the tree with list nodes remaining.
}
return head.val == root.val && (dfs(head.next, root.left) || dfs(head.next, root.right));
}
}
Python
class Solution:
def isSubPath(self, head: ListNode, root: TreeNode) -> bool:
if not root:
return (
False # Avoid NullPointerException by checking if root is null.
)
# Path can start from root => dfs
# Otherwise it can exist in left or right subtree
return (
self.dfs(head, root)
or self.isSubPath(head, root.left)
or self.isSubPath(head, root.right)
)
def dfs(self, head: ListNode, root: TreeNode) -> bool:
if not head:
return True # Reached end of linked list, so it matches.
if not root:
return False # Reached the end of a path in the tree with list nodes remaining.
return head.val == root.val and (
self.dfs(head.next, root.left) or self.dfs(head.next, root.right)
)
Complexity
- Time:
O(n * min(m, h))
wheren
is tree size, m is list size and h is the height of the tree. - Space:
O(h)
assuming recursion stack
%%
Method 2 - Use KMP
Find the Index of the First Occurrence in a String
%%