Linked List in Binary Tree
MedPrompt
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.
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: trueExample 3:
head
Constraints:
- The number of nodes in the tree will be in the range
[1, 2500]. - The number of nodes in the list will be in the range
[1, 100]. 1 <= Node.val <= 100for each node in the linked list and binary tree.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach involves traversing every node of the binary tree. For each node, we perform a separate check to see if a downward path starting from that node matches the entire linked list. This is straightforward but can be inefficient as it may re-check the same subpaths multiple times.
Algorithm
- Define a main function
isSubPath(head, root). - If
rootis null, returnfalseas no path can be formed. - Call a helper function
dfs(head, root)to check if a path matching the list starts at the currentroot. - If
dfsreturnstrue, we found a match, so returntrue. - Otherwise, recursively call
isSubPathon the left and right children:isSubPath(head, root.left) || isSubPath(head, root.right). - The helper function
dfs(listNode, treeNode)works as follows: - If
listNodeis null, returntrue(end of list reached). - If
treeNodeis null orlistNode.val != treeNode.val, returnfalse(path broken). - Return the result of checking the next list node against the left and right children:
dfs(listNode.next, treeNode.left) || dfs(listNode.next, treeNode.right).
Walkthrough
We define two recursive functions.
The main function, isSubPath(head, root), traverses the entire tree. Its purpose is to find a starting node in the tree that matches the head of the linked list.
- It checks three conditions:
- Does a path starting from the current
rootmatch the list? (This is checked by a helper function). - If not, does a matching path exist in the left subtree? (Recursive call:
isSubPath(head, root.left)). - If not, does a matching path exist in the right subtree? (Recursive call:
isSubPath(head, root.right)).
- Does a path starting from the current
- If any of these are true, we've found a match.
The helper function, dfs(listNode, treeNode), checks if a path starting from treeNode matches the list starting from listNode.
- Base Case 1: If
listNodeis null, it means we've successfully matched all elements of the list. Returntrue. - Base Case 2: If
treeNodeis null or the values don't match (treeNode.val != listNode.val), the path is broken. Returnfalse. - Recursive Step: If the current nodes match, we continue the search downwards. We check if the rest of the list (
listNode.next) matches a path starting from either the left child (treeNode.left) or the right child (treeNode.right). Returndfs(listNode.next, treeNode.left) || dfs(listNode.next, treeNode.right).
The initial call is isSubPath(head, root).
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } *//** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val = val; * this.left = left; * this.right = right; * } * } */class Solution { public boolean isSubPath(ListNode head, TreeNode root) { if (root == null) { return false; } // Check if a path starts from the current root if (dfs(head, root)) { return true; } // If not, check the left and right subtrees return isSubPath(head, root.left) || isSubPath(head, root.right); } // Helper function to check for a matching path from a given tree node private boolean dfs(ListNode head, TreeNode root) { // Base case: If we've reached the end of the list, we found a match if (head == null) { return true; } // Base case: If we've run out of tree nodes or values don't match if (root == null || head.val != root.val) { return false; } // Recursive step: Check left and right children for the next list node return dfs(head.next, root.left) || dfs(head.next, root.right); }}Complexity
Time
O(N * L), where N is the number of nodes in the tree and L is the length of the linked list. In the worst case, for each of the N tree nodes, we might traverse L nodes deep to check for a path match.
Space
O(H), where H is the height of the tree. This is due to the recursion stack depth. In the worst-case scenario of a skewed tree, H can be equal to N, making the space complexity O(N).
Trade-offs
Pros
Simple to understand and implement.
Uses a standard recursive pattern for tree problems.
Cons
Inefficient due to repeated computations. The
dfshelper might be called on the same nodes multiple times for different starting points.Can lead to a 'Time Limit Exceeded' error on large test cases.
Solutions
Solution
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val = val; * this.left = left; * this.right = right; * } * } */ class Solution { public boolean isSubPath ( ListNode head , TreeNode root ) { if ( root == null ) { return false ; } return dfs ( head , root ) || isSubPath ( head , root . left ) || isSubPath ( head , root . right ); } private boolean dfs ( ListNode head , TreeNode root ) { if ( head == null ) { return true ; } if ( root == null || head . val != root . val ) { return false ; } return dfs ( head . next , root . left ) || dfs ( head . next , root . right ); } }Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.