Similar Problems

Similar Problems not available

Number Of Good Leaf Nodes Pairs - Leetcode Solution

LeetCode:  Number Of Good Leaf Nodes Pairs Leetcode Solution

Difficulty: Medium

Topics: tree binary-tree depth-first-search  

Problem: Number of Good Leaf Nodes Pairs

Given the root of a binary tree, return the number of pairs (i, j) where i is a descendant of j, and both i and j are a leaf node.

Solution:

To solve this problem, we can first traverse the binary tree and get all the leaves. Then, for each leaf, we can find all the ancestors of that leaf and count the number of pairs (i, j) such that i is a descendant of j. To do this efficiently, we can use a recursive function that returns a set of ancestors for each leaf. We can then count all the pairs (i, j) for all leaves.

Here is the Python code for this approach:

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def countPairs(self, root: TreeNode) -> int:
        leaves = self.getLeaves(root)
        ancestors = {}
        self.getAncestors(root, leaves, ancestors)
        count = 0
        for leaf in leaves:
            for ancestor in ancestors[leaf]:
                if leaf != ancestor and leaf.val < ancestor.val:
                    count += 1
        return count

    def getLeaves(self, root):
        if not root:
            return []
        if not root.left and not root.right:
            return [root]
        return self.getLeaves(root.left) + self.getLeaves(root.right)

    def getAncestors(self, root, leaves, ancestors):
        if not root:
            return
        if root.left:
            self.getAncestors(root.left, leaves, ancestors)
            for leaf in leaves:
                if self.isDescendant(root.left, leaf):
                    if leaf not in ancestors:
                        ancestors[leaf] = set()
                    ancestors[leaf].add(root.left)
        if root.right:
            self.getAncestors(root.right, leaves, ancestors)
            for leaf in leaves:
                if self.isDescendant(root.right, leaf):
                    if leaf not in ancestors:
                        ancestors[leaf] = set()
                    ancestors[leaf].add(root.right)

    def isDescendant(self, ancestor, descendant):
        if not ancestor:
            return False
        if ancestor == descendant:
            return True
        return self.isDescendant(ancestor.left, descendant) or self.isDescendant(ancestor.right, descendant)

Explanation:

The countPairs function takes the root of the binary tree as input and returns the number of pairs (i, j) where i is a descendant of j, and both i and j are a leaf node.

First, we get all the leaves of the binary tree using the getLeaves function. This function uses a simple recursive approach to traverse the binary tree and return a list of all the leaf nodes.

Next, we create a dictionary called ancestors that will store the set of ancestors for each leaf node. We use a recursive function called getAncestors to find all the ancestors of each leaf. We iterate through all the leaves and check if each leaf is a descendant of the left or right subtree of each node. If it is, we add the node to the ancestors set of that leaf.

Finally, we iterate through all the leaves and their ancestors and count the number of pairs (i, j) where i is a descendant of j and i and j are not the same node. We return this count as the final answer.

Time Complexity: O(n^2) where n is the number of nodes in the binary tree. This is because we traverse the binary tree twice: once to get all the leaves and once to find the ancestors of each leaf. The isDescendant function also takes O(n) time in the worst case.

Space Complexity: O(n^2) where n is the number of nodes in the binary tree. This is because we store a dictionary of ancestors for each leaf, and each dictionary can have up to n-1 ancestors.

Number Of Good Leaf Nodes Pairs Solution Code

1