Как найти максимальную глубину дерева

Recursive mechanism to find max depth of depth of binary tree is very straightforward, but how can we do it efficiently without recursion as I have large tree where I would rather avoid this recursion.

//Recursive mechanism which I want to replace with non-recursive
private static int maxDepth(Node node) {
if (node == null) return 0;
    return 1 + Math.max(maxDepth(node.left), maxDepth(node.right)); 
}

PS: I am looking for answers in Java.

asked Nov 10, 2013 at 4:30

Hemant's user avatar

HemantHemant

4,5278 gold badges41 silver badges43 bronze badges

This variant uses two stacks, one for additional nodes to explore (wq) and one always containing the current path from the root (path). When we see the same node on the top of both stacks it means we’ve explored everything below it and can pop it. This is the time to update the tree depth too. On random or balanced trees the additional space should be O(log n), in the worst case O(n), of course.

static int maxDepth (Node r) {
    int depth = 0;
    Stack<Node> wq = new Stack<>();
    Stack<Node> path = new Stack<>();

    wq.push (r);
    while (!wq.empty()) {
        r = wq.peek();
        if (!path.empty() && r == path.peek()) {
            if (path.size() > depth)
                depth = path.size();
            path.pop();
            wq.pop();
        } else {
            path.push(r);
            if (r.right != null)
                wq.push(r.right);
            if (r.left != null)
                wq.push(r.left);
        }
    }

    return depth;
}

(Shameless plug: I had this idea for using dual stacks for non-recursive traversals a few weeks ago, check for a C++ code here http://momchil-velikov.blogspot.com/2013/10/non-recursive-tree-traversal.html not that I claim I was the first to invent it :)

answered Nov 11, 2013 at 19:43

chill's user avatar

chillchill

16.4k2 gold badges39 silver badges44 bronze badges

2

The recursive approach you’ve described is essentially a DFS over the binary tree. You can implement this iteratively if you’d like by storing an explicit stack of nodes and keeping track of the maximum depth encountered.

Hope this helps!

answered Nov 10, 2013 at 4:51

templatetypedef's user avatar

templatetypedeftemplatetypedef

360k101 gold badges890 silver badges1059 bronze badges

2

I have written following logic to do find max and min depth which doesn’t involve recursion and without increasing the space complexity.

// Find the maximum depth in the tree without using recursion
private static int maxDepthNoRecursion(TreeNode root) {
    return Math.max(maxDepthNoRecursion(root, true), maxDepthNoRecursion(root, false)); 
}

// Find the minimum depth in the tree without using recursion
private static int minDepthNoRecursion(TreeNode root) {
    return Math.min(maxDepthNoRecursion(root, true), maxDepthNoRecursion(root, false)); 
}

private static int maxDepthNoRecursion(TreeNode root, boolean left) {
    Stack<TreeNode> stack = new Stack<>();
    stack.add(root);
    int depth = 0;
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        if (left && node.left != null) stack.add(node.left);
        // Add the right node only if the left node is empty to find max depth
        if (left && node.left == null && node.right != null) stack.add(node.right); 
        if (!left && node.right != null) stack.add(node.right);
        // Add the left node only if the right node is empty to find max depth
        if (!left && node.right == null && node.left != null) stack.add(node.left);
        depth++;
    }
    return depth;
}

answered Nov 10, 2013 at 6:01

Hemant's user avatar

HemantHemant

4,5278 gold badges41 silver badges43 bronze badges

5

Another way is to use Level order traversal, where tree height is equal to the number of level of a tree. (It can only be use to calulate the minimal height of a tree.)

public int maxDepth(TreeNode root) {
    if (root == null) return 0;
    LinkedList<TreeNode> arr = new LinkedList<TreeNode>(); // queue for current level
    LinkedList<TreeNode> tmp = new LinkedList<TreeNode>(); // queue for next level
    arr.add(root);
    int res = 0; // result
    TreeNode node; // tmp node 
    while (true) {
        while (!arr.isEmpty()) {
            node = arr.poll();
            if (node.left != null) tmp.add(node.left);
            if (node.right != null) tmp.add(node.right);
        }
        res++;
        if (tmp.isEmpty()) break;
        arr = tmp;
        tmp = new LinkedList<TreeNode>();
    }
    return res;
}

answered Oct 11, 2015 at 17:10

vancexu's user avatar

vancexuvancexu

1,5483 gold badges19 silver badges30 bronze badges

Community's user avatar

answered Nov 10, 2013 at 4:36

Prasad K - Google's user avatar

Using a Array to store a layer of nodes, each time find a new layer. the depth plus one.

public int maxDepth2(TreeNode root){
        if(root == null){
            return 0;
        }

        int depth = 0;

        ArrayList<TreeNode> oneLayer = new ArrayList<TreeNode>();
        oneLayer.add(root);

        while(!oneLayer.isEmpty()){
            ArrayList<TreeNode> newLayer = new ArrayList<TreeNode>();
            for(TreeNode node:oneLayer){
                if(node.right!=null){
                    newLayer.add(node.right);
                }
                if(node.left!=null){
                    newLayer.add(node.left);
                }
            }
            oneLayer = newLayer;
            depth++;
        }

        return depth;
    }

answered Jan 4, 2016 at 7:18

Jerry Z.'s user avatar

Jerry Z.Jerry Z.

2,0313 gold badges22 silver badges28 bronze badges

Here is a BFS solution:

private class NodeHeight
{
    public Node node;
    public int height;

    public NodeHeight(Node n, int height)
    {
        node = n;
        this.height = height;
    }
}

public int GetHeightBfs(Node root)
{
    if(root == null)
        return 0;
    else
        return GetHeightBfs(new NodeHeight(root, 1))
}

private int GetHeightBfs(NodeHeight root)
{   
    int maxHeight = int.Min;
    int minHeight = int.Max;
    var q = new Queue<Node>();
    q.Enqueue(root);
    while(q.length > 0)
    {       
        var nodeHeight = q.Dequeue();
        var node = nodeHeight.node;
        int height = nodeHeight.height;
        if(node.left == null && node.right == null)
        {
            maxHeight = Math.max(maxHeight, height);
            minHeight = Math.min(minHeight, height);
        }

        if(node.left != null)
            q.Enqueue(new NodeHeight(node.left, height + 1);

        if(node.right != null)
            q.Enqueue(new NodeHeight(node.right, height + 1);
    }

    return maxHeight;
}   

Note that you can also return minHeight.
To make it DFS just replace Queue with Stack.

answered Sep 15, 2018 at 18:36

Yusuf Bhagat's user avatar

Это первый из Юэл164Второе обновление,166Оригинал

01 Предметы и препараты

Сегодня я представил 23-й выпуск легкого уровня в алгоритме LetCode (номер 104 названия). Дайте бинарное дерево, чтобы найти его максимальную глубину. Максимальная глубина — количество узлов на максимальном пути от корневого узла до максимального узера листьев. Листья являются узлами без дочерних узлов.

Например: учитывая бинарное дерево [3, 9, 20, NULL, NULL, 15, 7],

    3
   / 
  9  20
     / 
    15  7

Возвращает его глубину = 3.

Инструмент разработки, используемый в этом контексте, является Eclipse. Версия, используемая JDK, является 1.8, среда представляет собой Win7 64-битную систему, написанную и тестируйте с помощью языка Java.

02 Первое решение

Максимальная глубина — это количество узлов, содержащихся на корневом узле к траектору самого дальнеготельного листового узла. Возьмите два вилочных дерева выше, самый длинный путь имеет два: 3-> 20-> 15, 3-> 20-> 7, эти Два номера узлов на пути линии 3, поэтому, наконец, его глубина 3 выводы.

Особые обстоятельства: Когда входящее двоичное дерево пустое, у него нет узлов, его глубина 0.

Особые обстоятельства: Когда только корневой узел, его глубина 1, только его собственный узел.

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

Начиная с корневого узла, количество узлов составляет 1, потому что он имеет только один узел.

Введите узел дочернего узела корневого узла, в это время самый длинный путь должен рассчитать максимальный путь этого левого субпода и 20 этого правого ребенка. Очевидно, что 9 является узлом листьев, только один узел сама; и 20 имеет свой собственный Узел ребенка, на данный момент, вам нужно будет рассчитать самый длинный путь от 20.

20 Существует левый суб-узел 15, правый узел 7, а затем продолжают вычислять самый длительный путь 15 и 7, а 15 и 7 — это узлы листьев, поэтому количество узлов составляет всего 1, плюс 20 узлов Это относится к корневому узлу узел для детей, самый длинный путь в 20 узле 2.

Два подмазера 9, 20, максимальный путь узера 9 ребенка составляет 1, максимальное количество узлов равно 2, а максимальное значение принимается, а сам корневой узел добавляется. Количество узлов, 1 + 2 = 3, 3 — количество узлов на самом длинном пути, то есть глубина бинарного дерева.

Анализ здесь, мы знаем, чтобы рассчитать количество узлов из корневого узла в самый дальний узел листьев, вам необходимо рассчитать максимальный путь левого и правого дочерних узлов, и рассчитать максимальный путь левого и правого дочерних узлов, Он будет рассчитан. Они имеют самый длинный путь левого и правого дочерних узлов ниже, и мы можем использовать рекурсивный, после количества узлов нижнего листа, замечательный слой придумает максимум.

public int maxDepth(TreeNode root) {
    if (root == null) {
        return 0;
    }
    int left = maxDepth(root.left);
    int right = maxDepth(root.right);
    return 1 + Math.max(left, right);
}

03 Второе решение

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

public int maxDepth2(TreeNode root) {
    if (root == null) {
        return 0;
    }
    int depth = 0;
    Queue<TreeNode> q = new LinkedList<>();
    q.offer(root);
    while (!q.isEmpty()) {
        Queue<TreeNode> tem = new LinkedList<>();
        while(!q.isEmpty()){
            TreeNode node = q.poll();
            if (node.left != null) {
                tem.offer(node.left);
            }
            if (node.right != null) {
                tem.offer(node.right);
            }
        }
        q = tem;
        depth++;
    }
    return depth;
}

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

04 Третье решение

Второй метод решения имеет новую очередь для получения следующего слоя данных узла для ввода каждого цикла, может ли его изменять, сделать его более лаконичным? Здесь мы используем размер очереди, чтобы контролировать его, начиная с корневого узла, после ввода очереди размер очереди 1, начиная входить в цикл внутреннего слоя, после ходьбы один раз, очередь имеет два детских узла, в это время Размер 2, а затем продолжает запускать контур внутреннего слоя, пока все детские узлы не будут пройдены.

public int maxDepth3(TreeNode root) {
    if (root == null) {
        return 0;
    }
    int depth = 0;
    Queue<TreeNode> q = new LinkedList<>();
    q.offer(root);
    while (!q.isEmpty()) {
        int n = q.size();
        while(n-- > 0){
            TreeNode node = q.poll();
            if (node.left != null) {
                q.offer(node.left);
            }
            if (node.right != null) {
                q.offer(node.right);
            }
        }
        depth++;
    }
    return depth;
}

05 Проверка и тест

Для приведенных выше двух решений простая бинарное дерево провело тест на данные.

public static void main(String[] args) {
    Easy_104_MaximumDepthOfBinaryTree instance = new Easy_104_MaximumDepthOfBinaryTree();
    TreeNode t = new TreeNode(1);
    TreeNode t2 = new TreeNode(2);
    TreeNode t3 = new TreeNode(3);
    TreeNode t4 = new TreeNode(4);
    TreeNode t5 = new TreeNode(5);
    TreeNode t6 = new TreeNode(6);
    TreeNode t7 = new TreeNode(7);
    TreeNode t8 = new TreeNode(8);
    t.left = t2;
    t.right = t3;
    t2.left = t4;
    t2.right = t5;
    t3.left = t6;
    t3.right = t7;
    t7.left = t8;
    long start = System.nanoTime();
    int result = instance.maxDepth(t);
    long end = System.nanoTime();
    System.out.Println («MaxDepth --- Выход:» + Результат + ", при использовании:" + (конец-стартуе) / 1000 + "микросекунды");
    long start2 = System.nanoTime();
    int result2 = instance.maxDepth2(t);
    long end2 = System.nanoTime();
         System.out.Println («MaxDepth2 --- Выход:» + Realse2 + ", при использовании:" + (end2-start2) / 1000 + "микросекунды");
    long start3 = System.nanoTime();
    int result3 = instance.maxDepth3(t);
    long end3 = System.nanoTime();
         System.out.Println («MaxDepth3 --- Выход:» + Realse3 + ", при использовании:" + (end3-start3) / 1000 + "микросекунды");
}

Результаты теста следующие:

MaxDepth --- Выход: 4, время: 23 микросекунда
 Maxdepth2 --- Выход: 4, используемый: 586 микросекунд
 Maxdepth3 --- Выход: 4, используемый: 16 микросекунд

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

06 Маленький узел

Вышеупомянутое содержимое, если у вас есть какие-либо хорошие идеи решения, предложения или другие вопросы, вы можете отправить сообщение ниже, похвалы, оставьте сообщение, вперед — это самое большое возвращение и поддержка для меня!

Ivandur, большое спасибо.
shmkv, там просто дичь пишут, вот здесь дали нормальный понятный ответ.
А вот еще вопрос, у меня есть функция branches():

C++
1
2
3
4
5
6
7
8
9
10
11
int branches(TNode *&tr, int n) {
    int count = 0;
    if (tr == NULL)
        return 0;
 
    if (tr->data == n)
        return count;
 
    return ++count + branches(((tr->data > n) ? tr->left : tr->right), n);
 
}

Функция находит количество ветвей до заданной вершины. Я ввожу вершину и ищет все нормально, но если ввожу несуществующую вершину, он мне выдает место, где бы эта вершина располагалась, я писал различные условия, но ничего не выходит, если не трудно, помогите.

#python #tree

#python #дерево

Вопрос:

У меня есть древовидная структура данных, определенная как показано ниже:

 class Tree(object):
    def __init__(self, name='ROOT', children=None):
        self.name = name
        self.children = []
        if children is not None:
            for child in children:
                self.add_child(child)
    def __repr__(self):
        return self.name
    def add_child(self, node):
        assert isinstance(node, Tree)
        self.children.append(node)
 

Мне нужно написать функцию, чтобы найти глубину дерева. Вот функция, которую я написал (принимает дерево в качестве входных данных и возвращает целочисленное значение в качестве выходных данных), но она не дает правильного ответа:

 def depth(tree): 
    count = 1
    if len(tree.children) > 0:
        for child in tree.children:
            count = count   1
            depth(child)
    return count
 

Как мне это исправить?

Комментарии:

1. Что происходит с возвращаемым результатом при вызове depth(child) ?

2. Какое значение count имеет значение после 1?

3. Функция глубины неверна как рекурсивная функция. Вы должны установить count в качестве аргумента, например def depth(tree, count=1)

Ответ №1:

Хотя ваш depth(child) выполняет рекурсивный вызов, он ничего не делает с возвращаемым значением (глубина). Кажется, вы просто подсчитываете узлы на заданном уровне и называете это глубиной (на самом деле это ширина).

Что вам нужно, это что-то вроде (псевдокод):

 def maxDepth(node):
    # No children means depth zero below.

    if len(node.children) == 0:
        return 0

    # Otherwise get deepest child recursively.

    deepestChild = 0
    for each child in node.children:
        childDepth = maxDepth(child)
        if childDepth > deepestChild:
            deepestChild = childDepth

   # Depth of this node is one plus the deepest child.

   return 1   deepestChild
 

Ответ №2:

Как насчет того, чтобы просто рекурсивно увеличить максимальную глубину каждого узла?

 def max_depth(self, depth=0):
    if not self.children:
        return depth
    return max(child.max_depth(depth   1) for child in self.children)
 

Нахождение максимальной глубины двоичного дерева

На чтение 2 мин. Просмотров 20 Опубликовано 12.05.2021

Максимальная глубина двоичного дерева — это количество узлов от корня до самого дальнего листового узла. Другими словами, это высота двоичного дерева.

Рассмотрим двоичное дерево, показанное ниже:

Максимальная глубина или высота этого дерева составляет 4 4 4; узел 77 7 и узел 88 8 являются оба четырех узла удалены от корня .

Алгоритм

Алгоритм использует рекурсию для вычисления максимальной высоты:

  1. Рекурсивно вычислить высоту дерева слева от корня.
  2. Рекурсивно вычислить высоту дерева справа от корня.
  3. Выберите большую высоту из двух ответов и добавьте к ней одну (чтобы учесть корневой узел).

Код

  • C ++
  • C ++
  • C ++
  • Python
  • Python
  • Java
  • Java
  • C#
  • C#
 #include  using namespace std; struct Node {int value; Node * left, * right; Node (int val) {this-> value = val; this-> left = this-> right =  NULL;}}; int maxDepth (Node * root) {//нулевой корень означает, что дерево не существует.  если (корень == NULL) вернуть 0; //Получить глубину левого и правого поддерева//с помощью рекурсии.  int leftDepth = maxDepth (корень-> слева);  int rightDepth = maxDepth (корень-> вправо); //Выбираем больший и добавляем к нему корень. если (leftDepth> rightDepth) return leftDepth + 1;  else return rightDepth + 1;}//код драйвера int main () {Node * root = new Node (1);  root-> left = новый узел (2);  root-> right = новый узел (3);  root-> left-> left = новый узел (4);  root-> right-> left = новый узел (5);  root-> right-> right = новый узел (6);  root-> right-> right-> left = новый узел (8);  root-> right-> left-> right = новый узел (7);  cout   

Понравилась статья? Поделить с друзьями:
  • Составь рассказ по графику на с 86 учебника лес как природное сообщество
  • Ситуации как найти друга
  • Как исправить ошибку в декларации по прибыли за
  • Как найти понимающих людей
  • Ошибка h2o в стиральной машине hotpoint ariston как исправить ошибку