Leetcode 1367. Linked List in Binary Tree

Problem Explanation

In this problem, we need to return whether the elements of a linked list starting from the head form a subpath in a binary tree. A subpath is a descenton path that starts at a node in the tree.

For instance, consider the problem

1
2python
3head = [2,8], root = [1,4,4,null,2,2,null,1,null,6,8,null,null,null,null,1,3]

Here, the binary tree looks like the following:

1
2
3    1
4   / \
5  4   4
6 / \   \
72   2   1
8 \   \
9  6   8
10 / \   \
111   3  null

And the linked list looks like 2 -> 8. As you can see, we can form this linked link starting with node with val 2 and its right child 8.

Approach

We have to traverse the binary tree once and then check for each node if the tree rooted with this node contains the linked list in some connected downward path.

To implement this, we can traverse the tree with a depth-first approach for the first step and then use a helper function for the second step.

Python Solution

1
2python
3class Solution:
4    def isSubPath(self, head, root):
5        if not head: return True
6        if not root: return False
7        return self.helper(head, root) or self.isSubPath(head, root.left) or self.isSubPath(head, root.right)
8    
9    def helper(self, head, node):
10        if not head: return True
11        if not node or node.val != head.val: return False
12        return self.helper(head.next, node.left) or self.helper(head.next, node.right)

Java Solution

1
2java
3class Solution {
4    public boolean isSubPath(ListNode head, TreeNode root) {
5        if (head == null) return true;
6        if (root == null) return false;
7        return helper(head, root) || isSubPath(head, root.left) || isSubPath(head, root.right);
8    }
9    
10    private boolean helper(ListNode head, TreeNode node) {
11        if (head == null) return true;
12        if (node == null || node.val != head.val) return false;
13        return helper(head.next, node.left) || helper(head.next, node.right);
14    }
15}

JavaScript Solution

1
2javascript
3function ListNode(val, next) {
4  this.val = (val === undefined ? 0 : val)
5  this.next = (next === undefined ? null : next)
6} 
7
8function TreeNode(val, left, right) {
9  this.val = (val === undefined ? 0 : val)
10  this.left = (left === undefined ? null : left)
11  this.right = (right === undefined ? null : right)
12}
13
14var Solution = function() {
15  this.isSubPath = function(head, root) {
16    if (!head) return true;
17    if (!root) return false;
18    return this.helper(head, root) || this.isSubPath(head, root.left) || this.isSubPath(head, root.right);
19  }
20  
21  this.helper = function(head, node) {
22    if (!head) return true;
23    if (!node || node.val !== head.val) return false;
24    return this.helper(head.next, node.left) || this.helper(head.next, node.right);
25  }
26}

C++ Solution

1
2cpp
3class Solution {
4public:
5    bool isSubPath(ListNode* head, TreeNode* root) {
6        if (head == nullptr) return true;
7        if (root == nullptr) return false;
8        return helper(head, root) || isSubPath(head, root->left) || isSubPath(head, root->right);
9    }
10    
11private:
12    bool helper(ListNode* head, TreeNode* node) {
13        if (head == nullptr) return true;
14        if (node == nullptr || node->val != head->val) return false;
15        return helper(head->next, node->left) || helper(head->next, node->right);
16    }
17};

C# Solution

1
2csharp
3public class Solution {
4    public bool IsSubPath(ListNode head, TreeNode root) {
5        if (head == null) return true;
6        if (root == null) return false;
7        return Helper(head, root) || IsSubPath(head, root.left) || IsSubPath(head, root.right);
8    }
9    
10    private bool Helper(ListNode head, TreeNode node) {
11        if (head == null) return true;
12        if (node == null || node.val != head.val) return false;
13        return Helper(head.next, node.left) || Helper(head.next, node.right);
14    }
15}

Conclusion

The solution proposed above is a simple solution to check whether the values of a linked list form a subpath on a binary tree. By traversing the binary tree using a depth-first search and using a helper function, we're able to check each node of the tree and compare it to the elements of the linked list, ensuring we found a linked list as a sub-path in the binary tree.

In term of time complexity, this algorithm can take up to O(N) where N is the total number of nodes in the binary tree. This is because in the worst-case scenario, we might end up traversing each node in the tree. The space complexity is O(H) where H is the maximum height of the binary tree due to the space needed for the recursion stack. This is again considering the worst-case.

It's also essential to note that although the solution is given in Python, Java, JavaScript, C++, and C#, the principle remains the same across all languages. The main idea is to use a DFS traversal of the binary tree to find if there exists a subpath that matches the linked list.

Keep in mind, however, that while this approach works for this problem, it may not be the optimal solution for all similar problems. It's always important to analyze the problem at hand and devise the most efficient solution.


Got a question? Ask the Teaching Assistant anything you don't understand.

Still not clear? Ask in the Forum,  Discord or Submit the part you don't understand to our editors.


TA 👨‍🏫