[LeetCode] -árbol binario-5

prefacio

Registre las preguntas relacionadas con el árbol binario encontradas en el cepillado de preguntas de LeetCode, Parte 5

La espada apunta a la Oferta 26. La subestructura del árbol

Se usan dos funciones recursivas juntas, una es el método isSub(), que se usa para juzgar si B es una subestructura de A; la otra es el método isEqual(), que sirve para comparar si A y B son iguales, pero cuando B es nulo en comparación, también se consideran iguales; equivalente a juzgar si B es una subestructura de A, la premisa es que el nodo raíz de B coincide con el nodo raíz de A.

Específicamente, llame al método isSub () para juzgar si B es una subestructura de A. Si el valor de A es igual al valor de B en este momento, llame a isEqual () para juzgar si la parte con A como raíz es B en la estructura original La subestructura en A; si el valor de A no es igual al valor de B en este momento, vaya directamente a los subárboles izquierdo y derecho de A para encontrar la subestructura de B, es decir, isSub (A.izquierda,B) || esSub(A.derecha,B)

Para ser más popular , el método isSub () es encontrar el nodo cuyo valor es igual a B en A, y luego llamar al método isEqual () para juzgar si este nodo es la subestructura correspondiente a B, si lo es, devuelve verdadero , si no, continúe buscando el nodo A cuyo valor sea igual a B. Devuelve falso hasta que A sea nulo o devuelve verdadero si se encuentra una subestructura de B.

El método isEqual() agrega una condición basándose en juzgar si los dos árboles son iguales: si B es nulo, devuelve verdadero

class Solution {
    
    
    boolean isEqual(TreeNode A,TreeNode B){
    
    
        if(B == null) return true;
        if(A == null || A.val != B.val) return false;
        return isEqual(A.left,B.left) && isEqual(A.right,B.right);
    }
    boolean isSub(TreeNode A,TreeNode B){
    
    
        if(A == null) return false;
        if(A.val == B.val){
    
    
            if(isEqual(A.left,B.left) && isEqual(A.right,B.right)) return true;
        }
        return isSub(A.left,B) || isSub(A.right,B); 
    }
    public boolean isSubStructure(TreeNode A, TreeNode B) {
    
    
	    //特例先判断,如果有一棵树为 null 直接返回 false
        if(A == null || B == null) return false; 
        return isSub(A,B);
    }
}

572. Subárbol de otro árbol

Para juzgar si un árbol contiene subárboles de otro árbol, primero juzgue si el árbol actual es el mismo que otro árbol y, si no, búsquelo en los subárboles izquierdo y derecho.

Entonces aquí también necesitamos un método isThsSame() para determinar si dos árboles son iguales.

class Solution {
    
    
    public boolean isTheSame(TreeNode root,TreeNode subRoot){
    
    
        if(root == null && subRoot == null) return true;
        if((root == null && subRoot != null) || (root != null && subRoot == null)) return false;
        if(root.val != subRoot.val) return false;
        return isTheSame(root.left,subRoot.left) && isTheSame(root.right,subRoot.right);
    }
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
    
    
        if(root == null && subRoot == null) return true;
        if((root == null && subRoot != null) || (root != null && subRoot == null)) return false;
        if(isTheSame(root,subRoot)) return true;
        return isSubtree(root.left,subRoot) || isSubtree(root.right,subRoot);
    }
}

100.El mismo árbol

Para determinar si dos árboles son iguales, primero determine si las raíces son iguales y luego primero determine si los subárboles izquierdos son iguales. Si los subárboles izquierdos no son iguales, puede devolver falso sin juzgar si los subárboles derechos son iguales. Si los subárboles izquierdos también son iguales, entonces devuelve el resultado de si el subárbol derecho es el mismo.

public boolean isSameTree(TreeNode p, TreeNode q) {
    
    
	//防止下面.val和.left .right出现空指针异常,
	//所有两棵树可能为null的情况都要先判断
    if(p == null && q==null)return true;
    if(p== null || q == null) return false;
    if(p.val != q.val) return false;
    boolean left = isSameTree(p.left,q.left);
    if(left == false) return false;
    return isSameTree(p.right,q.right);
}

101. Árbol binario simétrico

Si la raíz está vacía, devuelve verdadero directamente; de ​​lo contrario, compara si el hijo izquierdo es igual al hijo derecho, y si son iguales, compara si el hijo izquierdo del hijo izquierdo es igual al hijo derecho del hijo derecho. , y si el hijo derecho del hijo izquierdo es igual al hijo izquierdo del hijo derecho...

Por analogía, la función recursiva juzga si los valores de dos nodos simétricos son iguales. Si son iguales, juzga si el hijo izquierdo del nodo izquierdo es igual al hijo derecho del nodo derecho y si el hijo derecho del hijo izquierdo es igual al hijo izquierdo del nodo derecho. Sólo si estas dos relaciones son iguales podemos explicar la simetría

class Solution {
    
    
    public boolean rec(TreeNode l,TreeNode r){
    
    
        if(l == null && r != null) return false;
        if(l != null && r == null) return false;
        if(l == null && r == null) return true;
        if(l.val != r.val) return false;
        return rec(l.left,r.right) && rec(l.right,r.left);
    }
    public boolean isSymmetric(TreeNode root) {
    
    
        if(root == null) return true;
        return rec(root.left,root.right);
    }
}

662. Ancho máximo del árbol binario.

En primer lugar, el ancho no puede considerarse como el número total de nodos en cada capa, el ancho mencionado aquí solo está relacionado con la distancia entre el nodo más a la izquierda y el nodo más a la derecha de cada capa.

Basado en el recorrido en profundidad primero (recorrido de preorden), cada nodo corresponde a un subíndice pos (que puede considerarse como un árbol binario almacenado en una estructura de secuencia de matriz) , y luego el hijo izquierdo corresponde a 2 * pos, y el hijo derecho corresponde a 2 * pos +1. Durante el proceso de recorrido, se registra el número actual de capas y luego, entre cada capa, la distancia con la mayor diferencia en subíndices es la altura requerida.

Como no conocemos la profundidad máxima, no podemos usar una matriz y solo podemos usar un mapa para guardar el índice del nodo más a la izquierda de cada capa.
Dado que se basa en el recorrido de preorden, podemos saber que el El primer nodo atravesado en cada capa es el último nodo de cada capa. El nodo izquierdo
registra el índice del nodo más a la izquierda de cada capa, y luego, al acceder a un nodo con el mismo número de capas más adelante, puede restar el valor del índice de este nodo a partir del valor de índice del nodo más a la izquierda para obtener un ancho y luego compararlo con ¿Cuál de los anchos máximos obtenidos anteriormente es mayor?

class Solution {
    
    
    int ans;
    Map<Integer, Integer> left;
    public int widthOfBinaryTree(TreeNode root) {
    
    
        ans = 0;
        left = new HashMap();
        dfs(root, 0, 1);
        return ans;
    }
    //depth 维护当前遍历到的深度,pos 维护当前要访问的节点的下标
    public void dfs(TreeNode root, int depth, int pos) {
    
    
        if (root == null) return;
        //记录最左边节点的索引。putIfAbsent 是指要存的 key不存在才放入这个键值对,这样就不会覆盖原有 key 的值
        left.putIfAbsent(depth, pos); 
        //更新维护最大宽度。而且要前面先 put 了再来算这个宽度,否则,当遍历到的是每层的第一个节点时
        //left调用get(depth)为null
        ans = Math.max(ans, pos - left.get(depth) + 1); 
        dfs(root.left, depth + 1, 2 * pos);
        dfs(root.right, depth + 1, 2 * pos + 1);
    }
}

104.La profundidad máxima de un árbol binario.

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

111.Profundidad mínima del árbol binario.

public int minDepth(TreeNode root) {
    
    
     if(root == null) return 0;
     int left = minDepth(root.left);
     int right = minDepth(root.right);
     //如果left为0,说明左儿子为空,如果此时right不为0,说明叶子节点应该在右子树上找
     //也有可能left跟right都为0,那么当前节点就是叶子结点,return1
     if(left == 0) return 1 + right;
     if(right == 0) return 1 + left;
     //如果left,right都不为0,说明左右子树都不为空,所以最小深度是两棵子树中最小深度的较小值
     return 1 + Math.min(left,right);
 }

513. Encuentra el valor de la esquina inferior izquierda del árbol.

Según el recorrido del pedido previo, el nodo más a la izquierda de cada capa debe ser el primer nodo visitado en esa capa. Por lo tanto, se puede mantener el número de capa del nodo visitado actualmente y al mismo tiempo se puede registrar el número máximo de capa maxLayer que se ha visitado.Siempre que la capa actual sea mayor que maxLayer, significa que la capa actualmente visitada El nodo es el nodo más a la izquierda de la capa de capa, así que registre el valor de este nodo val.

Por analogía, al final de la visita, el valor registrado es el valor del nodo más a la izquierda en el nivel inferior, que es el valor en la esquina inferior izquierda del árbol.

class Solution {
    
    
    int maxLayer = -1;
    int val = -1;
    public void rec(TreeNode root,int layer){
    
    
        if(root == null) return;
        if(layer > maxLayer){
    
    
            val = root.val;
            maxLayer = layer;
        }
        rec(root.left,layer + 1);
        rec(root.right,layer + 1);
    }
    public int findBottomLeftValue(TreeNode root) {
    
    
        rec(root,0);
        return val;
    }
}

おすすめ

転載: blog.csdn.net/Pacifica_/article/details/125793101