leetcode.116. Llene el siguiente puntero de nodo derecho de cada nodo

Llene el siguiente puntero de nodo derecho de cada nodo

Problema
Dado un árbol binario perfecto, todos sus nodos hoja están al mismo nivel y cada nodo padre tiene dos nodos hijos. El árbol binario se define de la siguiente manera:

struct Node { int val; Node * left; Node * right; Node * next; } Llene cada uno de sus siguientes punteros de modo que este puntero apunte a su siguiente nodo derecho. Si no se puede encontrar el siguiente nodo derecho, el siguiente puntero se establece en NULL.





En el estado inicial, todos los punteros siguientes se establecen en NULL.
Ejemplo:
Inserte la descripción de la imagen aquí

输入:{
    
    "$id":"1","left":{
    
    "$id":"2","left":{
    
    "$id":"3","left":null,"next":null,"right":null,"val":4},"next":null,"right":{
    
    "$id":"4","left":null,"next":null,"right":null,"val":5},"val":2},"next":null,"right":{
    
    "$id":"5","left":{
    
    "$id":"6","left":null,"next":null,"right":null,"val":6},"next":null,"right":{
    
    "$id":"7","left":null,"next":null,"right":null,"val":7},"val":3},"val":1}

输出:{
    
    "$id":"1","left":{
    
    "$id":"2","left":{
    
    "$id":"3","left":null,"next":{
    
    "$id":"4","left":null,"next":{
    
    "$id":"5","left":null,"next":{
    
    "$id":"6","left":null,"next":null,"right":null,"val":7},"right":null,"val":6},"right":null,"val":5},"right":null,"val":4},"next":{
    
    "$id":"7","left":{
    
    "$ref":"5"},"next":null,"right":{
    
    "$ref":"6"},"val":3},"right":{
    
    "$ref":"4"},"val":2},"next":null,"right":{
    
    "$ref":"7"},"val":1}

解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。

rápido:

  • Solo puede utilizar espacio extra constante.
  • El uso de la recursividad para resolver el problema también cumple los requisitos El espacio de pila ocupado por el programa recursivo en este problema no se cuenta como complejidad de espacio adicional.

Ideas

Ver a un árbol binario, lo primero que debe pensar es preorden de recorrido , de orden transversal media , orden posterior recorrido , primera búsqueda en profundidad ( DFS ), búsqueda en anchura ( BFS ).
Este problema es más fácil de resolver con el método de primera búsqueda en amplitud ( BFS ).

    public void levelOrder(TreeNode tree) {
    
    
        if (tree == null)
            return;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(tree);//相当于把数据加入到队列尾部
        while (!queue.isEmpty()) {
    
    
            //poll方法相当于移除队列头部的元素
            TreeNode node = queue.poll();
            System.out.println(node.val);
            if (node.left != null)
                queue.add(node.left);
            if (node.right != null)
                queue.add(node.right);
        }
    }

Modifíquelo para obtener el método uno.

Método 1: cruce de nivel

Inserte la descripción de la imagen aquí

class Solution {
    
    
    public Node connect(Node root) {
    
    
        if (root == null) {
    
    
            return root;
        }
        
        // 初始化队列同时将第一层节点加入队列中,即根节点
        Queue<Node> queue = new LinkedList<Node>(); 
        queue.add(root);
        
        // 外层的 while 循环迭代的是层数
        while (!queue.isEmpty()) {
    
    
            
            // 记录当前队列大小
            int size = queue.size();
            
            // 遍历这一层的所有节点
            for (int i = 0; i < size; i++) {
    
    
                
                // 从队首取出元素
                Node node = queue.poll();
                
                // 连接
                if (i < size - 1) {
    
    
                    node.next = queue.peek();
                }
                
                // 拓展下一层节点
                if (node.left != null) {
    
    
                    queue.add(node.left);
                }
                if (node.right != null) {
    
    
                    queue.add(node.right);
                }
            }
        }
        
        // 返回根节点
        return root;
    }
}

Método 2: use el siguiente puntero establecido

Si el nodo actual es el nodo izquierdo, conocemos el nodo padre del nodo actual, entonces es fácil conectar su nodo derecho (tenga en cuenta que el título es un árbol binario perfecto).
Inserte la descripción de la imagen aquí
Pero el problema es que los nodos padres de dos nodos en la misma capa son diferentes, como se muestra en la figura siguiente.
Inserte la descripción de la imagen aquí
Si los nodos de la capa superior están conectados, ¿puede encontrar su próximo nodo a través de la capa superior?
Inserte la descripción de la imagen aquí
y entonces

curr.right.next = curr.next.left;

Específicamente :

Comience desde el nodo raíz. Debido a que solo hay un nodo en el nivel 0, no se requiere procesamiento. Puede establecerse como una capa en una capa debajo nextdel puntero. El punto más importante de este método es establecer un nextpuntero para la x + 1ª capa cuando está en la xª capa . Una vez que se completen estas operaciones de conexión, muévase a la capa x + 1 para establecer el siguiente puntero para la capa x + 2.
Al atravesar los nodos de una capa, nextse ha establecido el puntero del nodo de la capa . Esto ahorra espacio al eliminar la necesidad de colas. Cada vez que conoce el nodo más a la izquierda de la siguiente capa, puede comenzar desde ese nodo y atravesar todos los nodos de esta capa como si estuviera atravesando una lista vinculada.

Código

class Solution {
    
    
    public Node connect(Node root) {
    
    
        if (root == null) {
    
    
            return root;
        }
        
        // 从根节点开始
        Node leftmost = root;
        
        while (leftmost.left != null) {
    
    
            
            // 遍历这一层节点组织成的链表,为下一层的节点更新 next 指针
            Node head = leftmost;
            
            while (head != null) {
    
    
                
                // CONNECTION 1
                head.left.next = head.right;
                
                // CONNECTION 2
                if (head.next != null) {
    
    
                    head.right.next = head.next.left;
                }
                
                // 指针向后移动
                head = head.next;
            }
            
            // 去下一层的最左的节点
            leftmost = leftmost.left;
        }
        
        return root;
    }
}

Recursividad

Si comprende la forma del nivel anterior, no es difícil entender dfs.

    public Node connect(Node root) {
    
    
        dfs(root, null);
        return root;
    }

    private void dfs(Node curr, Node next) {
    
    
        if (curr == null)
            return;
        curr.next = next;
        dfs(curr.left, curr.right);
        dfs(curr.right, curr.next == null ? null : curr.next.left);
    }

Consulte
4 formas de resolver BFS y recursividad (las últimas 3 formas derrotaron al 100% de los usuarios)

Supongo que te gusta

Origin blog.csdn.net/e891377/article/details/109091232
Recomendado
Clasificación