1530. Number of Good Leaf Nodes Pairs

Вам дан корень бинарного дерева и целое число distance. Пара двух различных листовых узлов бинарного дерева называется хорошей, если длина кратчайшего пути между ними меньше или равна distance.

Верните количество хороших пар листовых узлов в дереве.

Пример:

Input: root = [1,2,3,null,4], distance = 3

Output: 1

Explanation: The leaf nodes of the tree are 3 and 4 and the length of the shortest path between them is 3. This is the only good pair.

C# решение

сопоставлено/оригинал
public class Solution {
    public int CountPairs(TreeNode root, int distance) {
        var graph = new Dictionary<TreeNode, List<TreeNode>>();
        var leafNodes = new HashSet<TreeNode>();
        TraverseTree(root, null, graph, leafNodes);
        int ans = 0;
        foreach (var leaf in leafNodes) {
            var bfsQueue = new Queue<TreeNode>();
            var seen = new HashSet<TreeNode>();
            bfsQueue.Enqueue(leaf);
            seen.Add(leaf);
            for (int i = 0; i <= distance; i++) {
                int size = bfsQueue.Count;
                for (int j = 0; j < size; j++) {
                    var currNode = bfsQueue.Dequeue();
                    if (leafNodes.Contains(currNode) && currNode != leaf) {
                        ans++;
                    }
                    if (graph.ContainsKey(currNode)) {
                        foreach (var neighbor in graph[currNode]) {
                            if (!seen.Contains(neighbor)) {
                                bfsQueue.Enqueue(neighbor);
                                seen.Add(neighbor);
                            }
                        }
                    }
                }
            }
        }
        return ans / 2;
    }
    private void TraverseTree(TreeNode currNode, TreeNode prevNode,
                              Dictionary<TreeNode, List<TreeNode>> graph, HashSet<TreeNode> leafNodes) {
        if (currNode == null) {
            return;
        }
        if (currNode.left == null && currNode.right == null) {
            leafNodes.Add(currNode);
        }
        if (prevNode != null) {
            if (!graph.ContainsKey(prevNode)) {
                graph[prevNode] = new List<TreeNode>();
            }
            graph[prevNode].Add(currNode);
            if (!graph.ContainsKey(currNode)) {
                graph[currNode] = new List<TreeNode>();
            }
            graph[currNode].Add(prevNode);
        }
        TraverseTree(currNode.left, currNode, graph, leafNodes);
        TraverseTree(currNode.right, currNode, graph, leafNodes);
    }
}

C++ решение

auto-draft, проверить перед отправкой
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
    public int CountPairs(TreeNode root, int distance) {
        var graph = new unordered_map<TreeNode, List<TreeNode>>();
        var leafNodes = new HashSet<TreeNode>();
        TraverseTree(root, null, graph, leafNodes);
        int ans = 0;
        foreach (var leaf in leafNodes) {
            var bfsQueue = new queue<TreeNode>();
            var seen = new HashSet<TreeNode>();
            bfsQueue.Enqueue(leaf);
            seen.push_back(leaf);
            for (int i = 0; i <= distance; i++) {
                int size = bfsQueue.size();
                for (int j = 0; j < size; j++) {
                    var currNode = bfsQueue.Dequeue();
                    if (leafNodes.Contains(currNode) && currNode != leaf) {
                        ans++;
                    }
                    if (graph.count(currNode)) {
                        foreach (var neighbor in graph[currNode]) {
                            if (!seen.Contains(neighbor)) {
                                bfsQueue.Enqueue(neighbor);
                                seen.push_back(neighbor);
                            }
                        }
                    }
                }
            }
        }
        return ans / 2;
    }
    private void TraverseTree(TreeNode currNode, TreeNode prevNode,
                              unordered_map<TreeNode, List<TreeNode>> graph, HashSet<TreeNode> leafNodes) {
        if (currNode == null) {
            return;
        }
        if (currNode.left == null && currNode.right == null) {
            leafNodes.push_back(currNode);
        }
        if (prevNode != null) {
            if (!graph.count(prevNode)) {
                graph[prevNode] = new List<TreeNode>();
            }
            graph[prevNode].push_back(currNode);
            if (!graph.count(currNode)) {
                graph[currNode] = new List<TreeNode>();
            }
            graph[currNode].push_back(prevNode);
        }
        TraverseTree(currNode.left, currNode, graph, leafNodes);
        TraverseTree(currNode.right, currNode, graph, leafNodes);
    }
}

Java решение

сопоставлено/оригинал
class Solution {

    public int countPairs(TreeNode root, int distance) {
        Map<TreeNode, List<TreeNode>> graph = new HashMap<>();
        Set<TreeNode> leafNodes = new HashSet<>();
        traverseTree(root, null, graph, leafNodes);
        int ans = 0;
        for (TreeNode leaf : leafNodes) {
            Queue<TreeNode> bfsQueue = new LinkedList<>();
            Set<TreeNode> seen = new HashSet<>();
            bfsQueue.add(leaf);
            seen.add(leaf);
            for (int i = 0; i <= distance; i++) {
                int size = bfsQueue.size();
                for (int j = 0; j < size; j++) {
                    TreeNode currNode = bfsQueue.remove();
                    if (leafNodes.contains(currNode) && currNode != leaf) {
                        ans++;
                    }
                    if (graph.containsKey(currNode)) {
                        for (TreeNode neighbor : graph.get(currNode)) {
                            if (!seen.contains(neighbor)) {
                                bfsQueue.add(neighbor);
                                seen.add(neighbor);
                            }
                        }
                    }
                }
            }
        }
        return ans / 2;
    }

    private void traverseTree(
        TreeNode currNode,
        TreeNode prevNode,
        Map<TreeNode, List<TreeNode>> graph,
        Set<TreeNode> leafNodes
    ) {
        if (currNode == null) {
            return;
        }
        if (currNode.left == null && currNode.right == null) {
            leafNodes.add(currNode);
        }
        if (prevNode != null) {
            graph.computeIfAbsent(prevNode, k -> new ArrayList<TreeNode>());
            graph.get(prevNode).add(currNode);
            graph.computeIfAbsent(currNode, k -> new ArrayList<TreeNode>());
            graph.get(currNode).add(prevNode);
        }
        traverseTree(currNode.left, currNode, graph, leafNodes);
        traverseTree(currNode.right, currNode, graph, leafNodes);
    }
}

Python решение

сопоставлено/оригинал
class Solution:
    def countPairs(self, root: TreeNode, distance: int) -> int:
        graph = defaultdict(list)
        leafNodes = set()
        self.traverseTree(root, None, graph, leafNodes)
        ans = 0
        for leaf in leafNodes:
            bfsQueue = deque([leaf])
            seen = set([leaf])
            for i in range(distance + 1):
                size = len(bfsQueue)
                for _ in range(size):
                    currNode = bfsQueue.popleft()
                    if currNode in leafNodes and currNode != leaf:
                        ans += 1
                    for neighbor in graph[currNode]:
                        if neighbor not in seen:
                            bfsQueue.append(neighbor)
                            seen.add(neighbor)
        return ans // 2

    def traverseTree(self, currNode, prevNode, graph, leafNodes):
        if not currNode:
            return
        if not currNode.left and not currNode.right:
            leafNodes.add(currNode)
        if prevNode:
            graph[prevNode].append(currNode)
            graph[currNode].append(prevNode)
        self.traverseTree(currNode.left, currNode, graph, leafNodes)
        self.traverseTree(currNode.right, currNode, graph, leafNodes)

Go решение

сопоставлено/оригинал
type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}

func countPairs(root *TreeNode, distance int) int {
    graph := make(map[*TreeNode][]*TreeNode)
    leafNodes := make(map[*TreeNode]bool)
    traverseTree(root, nil, graph, leafNodes)

    ans := 0
    for leaf := range leafNodes {
        bfsQueue := []*TreeNode{leaf}
        seen := make(map[*TreeNode]bool)
        seen[leaf] = true

        for i := 0; i <= distance; i++ {
            size := len(bfsQueue)
            for j := 0; j < size; j++ {
                currNode := bfsQueue[0]
                bfsQueue = bfsQueue[1:]

                if leafNodes[currNode] && currNode != leaf {
                    ans++
                }

                for _, neighbor := range graph[currNode] {
                    if !seen[neighbor] {
                        bfsQueue = append(bfsQueue, neighbor)
                        seen[neighbor] = true
                    }
                }
            }
        }
    }
    return ans / 2
}

func traverseTree(currNode, prevNode *TreeNode, graph map[*TreeNode][]*TreeNode, leafNodes map[*TreeNode]bool) {
    if currNode == nil {
        return
    }
    if currNode.Left == nil && currNode.Right == nil {
        leafNodes[currNode] = true
    }
    if prevNode != nil {
        graph[prevNode] = append(graph[prevNode], currNode)
        graph[currNode] = append(graph[currNode], prevNode)
    }
    traverseTree(currNode.Left, currNode, graph, leafNodes)
    traverseTree(currNode.Right, currNode, graph, leafNodes)
}

Algorithm

Инициализируйте список смежности для преобразования дерева в граф и множество для хранения листовых узлов. Используйте вспомогательный метод traverseTree для обхода дерева, чтобы построить граф и найти листовые узлы. В параметрах поддерживайте текущий узел, а также родительский узел. Если текущий узел является листом, добавьте его в множество. В списке смежности добавьте текущий узел в список соседей родительского узла и наоборот. Рекурсивно вызовите traverseTree для левого и правого дочернего узла текущего узла.

Инициализируйте переменную ans для подсчета количества хороших пар листовых узлов. Итеративно переберите каждый листовой узел в множестве. Запустите BFS для текущего листового узла. BFS можно прервать досрочно, как только будут обнаружены все узлы, находящиеся на расстоянии от текущего листового узла. Увеличьте ans для каждого листового узла, найденного в каждом запуске BFS.

Верните ans / 2. Мы считаем каждую пару дважды, поэтому нужно разделить на 2, чтобы получить фактическое количество.

😎

Вакансии для этой задачи

Показаны активные вакансии с пересечением по тегам задачи.

Все вакансии
Активных вакансий пока нет.