Algoritmo de hoy 04: reconstrucción de un árbol binario

1. Descripción del tema

Enlace del problema: leetcode.cn/problems/zh…

Dificultad: Moderada

Ingrese los resultados del recorrido en orden previo y el recorrido en orden de un árbol binario, construya el árbol binario y devuelva su nodo raíz.

Suponga que ni el recorrido en orden previo de entrada ni los resultados del recorrido en orden contienen números duplicados.

2. Ideas para resolver problemas

divide y conquistaras

Preordenar propiedades transversales: los nodos se [ 根节点 | 左子树 | 右子树 ]ordenan por .

Propiedades transversales en orden: los nodos se [ 左子树 | 根节点 | 右子树 ]ordenan por .

Con base en las propiedades anteriores, se pueden extraer las siguientes inferencias:

El primer valor del recorrido en orden previo es el valor del nodo raíz. Use este valor para dividir el resultado del recorrido en orden en dos partes. La parte izquierda es el resultado del recorrido en orden del subárbol izquierdo del árbol, y la parte derecha es el resultado de recorrido en orden del subárbol derecho del árbol. Luego resuelva recursivamente los subárboles izquierdo y derecho respectivamente.

Para resolver este tipo de problemas, es adecuado utilizar la idea de divide y vencerás.El código de divide y vencerás se puede resumir en la siguiente estructura:

 def divide_conquer(problem, param1, param2, ...):
     # 1.终止条件
     if problem is None:
         print_result
         return
     # 2.准备数据
     data = prepare_data(problem)
     subproblems = split_problem(problem, data)
     # 3.处理子问题
     subresult1 = self.divide_conquer(subproblems[0], p1, ...)
     subresult2 = self.divide_conquer(subproblems[1], p1, ...)
     subresult3 = self.divide_conquer(subproblems[1], p1, ...)
     # ...
     
     result = process_result(subresult1, subresult2, subresult3, ...)

Análisis del algoritmo divide y vencerás:

  1. Condiciones de terminación: el índice del nodo raíz en el recorrido en orden previo root, el límite izquierdo del subárbol en el recorrido en orden preLy el límite derecho del subárbol en el recorrido en orden preR; cuando preL > preRsignifica que el nodo hoja se ha cruzado, se devuelve nulo en este momento;

  2. Preparar datos:

    • Cree un nodo raíz node: el valor del nodo es preorder[root];
    • Divida los subárboles izquierdo y derecho: encuentre inorderel índice del nodo raíz en el recorrido en orden i;
  3. Manejar subproblemas: habilitar la recursividad del subárbol izquierdo y derecho;

    índice de nodo raíz Límite izquierdo de recorrido en orden Límites rectos transversales en orden
    subárbol izquierdo raíz + 1 izquierda yo - 1
    subárbol derecho i - izquierda + raíz + 1 yo + 1 bien

Análisis de Complejidad

Complejidad temporal: O(N), donde N es el número de nodos del árbol. La inicialización de HashMap debe atravesar en orden, lo que toma O (N). Se establecen recursivamente un total de N nodos, y las operaciones de establecimiento y búsqueda de nodos en cada capa de recursividad toman O(1), por lo que se utiliza el tiempo O(N).

Complejidad del espacio: O(N), HashMap usa O(N) espacio adicional; en el peor de los casos (cuando el árbol binario de entrada es una lista enlazada), la profundidad de recurrencia alcanza N, ocupando el espacio del marco de pila O(N); por lo que un total de O(N) se usa N) espacio.

3. Implementación del código

 // 缓存中序遍历数组每个值对应的索引
 private Map<Integer, Integer> indexForInOrders = new HashMap<>();
 ​
 public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
     for (int i = 0; i < in.length; i++)
         indexForInOrders.put(in[i], i);
     return reConstructBinaryTree(pre, 0, pre.length - 1, 0);
 }
 ​
 private TreeNode reConstructBinaryTree(int[] pre, int preL, int preR, int inL) {
     if (preL > preR)
         return null;
     TreeNode root = new TreeNode(pre[preL]);
     int inIndex = indexForInOrders.get(root.val);
     int leftTreeSize = inIndex - inL;
     root.left = reConstructBinaryTree(pre, preL + 1, preL + leftTreeSize, inL);
     root.right = reConstructBinaryTree(pre, preL + leftTreeSize + 1, preR, inL + leftTreeSize + 1);
     return root;
 }

Lectura recomendada

la cubierta

Serie de algoritmos de hoy, dirección de actualización de la solución: studeyang.tech/2023/0718.h...

Supongo que te gusta

Origin juejin.im/post/7257077672362246203
Recomendado
Clasificación