Árbol de entrenamiento del algoritmo elemental de LeetCode (Completado)

Introducción

Anterior: Lista vinculada al entrenamiento del algoritmo primario de LeetCode

Siguiente: LeetCode Elementary Algorithm Training-Sorting and Search

Originalmente quería comenzar con el nivel principiante e intermedio y los algoritmos de entrevistas corporativas, pero al final optamos por comenzar desde lo básico, porque no cepillamos preguntas con el propósito de cepillar preguntas, sino ejercitar una especie de algoritmo pensando en el proceso de cepillado de preguntas, después de mucho entrenamiento. Forme una visión única del algoritmo, cultive la sensibilidad al algoritmo, vea el problema, un plan para resolver el problema puede aparecer en el cerebro y, lentamente, genere confianza desde el principio, y esto también es para el complejo algoritmo detrás Sentar las bases para ideas de resolución de problemas.

Introducción al algoritmo primario de LeetCode

Si también quieres entrenar tu propio pensamiento algorítmico, también puedes unirte a mí, comenzando desde el algoritmo elemental, inicia tu viaje del algoritmo: algoritmo elemental .

Un poco de su propio pensamiento: no mire la respuesta después de leer la pregunta y luego recite la pregunta, de modo que la memoria del algoritmo implementado no sea fuerte, debe tener su propio pensamiento; y no escriba sobre IDEA al principio, Asegúrese de intentar escribirlo en la pizarra proporcionada por leetCode y finalmente colóquelo en IDEA para ver si hay algún problema, a fin de consolidar su uso y competencia básica de API; otro punto es ser audaz, no el costo de prueba y error en la entrevista Baja, intenta incorporar nuestras ideas al código.

Debido a problemas de espacio, el blog solo enumera ejemplos y sus propias respuestas de resolución de problemas. Para obtener más detalles, puede hacer clic directamente en el tema para ver.

Profundidad máxima del árbol binario

Dado un árbol binario, encuentre su profundidad máxima.
La profundidad del árbol binario es el número de nodos en la ruta más larga desde el nodo raíz hasta el nodo hoja más lejano.

Explicación: Un nodo hoja se refiere a un nodo sin nodos secundarios.

Ejemplo:
dado un árbol binario [3,9,20, null, null, 15,7],

 	3
   / \
  9  20
    /  \
   15   7

Devuelve su profundidad máxima 3.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) return 0;
        int max = 1;
        int leftMax = maxDepth(root.left);
        int rightMax = maxDepth(root.right);
    
        return max + Math.max(leftMax,rightMax);
    }
}

39/39 casos de prueba aprobados
Estado: Aprobado Tiempo de
ejecución: 0 ms
Consumo de memoria: 40 MB

Esta recursión debe devolver 0 cuando el nodo es nulo, y el valor predeterminado es 1 si el nodo no es nulo, y luego continuar profundizando en los nodos secundarios izquierdo y derecho, el que sea mayor devuelve, max + (el más grande de leftMax y rightMax), y así sucesivamente.

Verificar el árbol de búsqueda binaria

Dado un árbol binario, juzgue si es un árbol de búsqueda binario válido.
Suponga que un árbol de búsqueda binario tiene las siguientes características:
el subárbol izquierdo de un nodo solo contiene números menores que el nodo actual.
El subárbol derecho del nodo solo contiene números mayores que el nodo actual.
Todos los subárboles izquierdo y derecho deben ser árboles de búsqueda binarios.

Ejemplo 1:
Entrada:

    2
   / \
  1   3

Salida: verdadero

Ejemplo 2:
Entrada:

    5
   / \
  1   4
     / \
    3   6

Salida: falso
Explicación: La entrada es: [5,1,4, nulo, nulo, 3,6].
El valor del nodo raíz es 5, pero el valor de su nodo hijo derecho es 4.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
   public boolean help(TreeNode root,Integer min,Integer max){
      if(root == null) return true;
        int val = root.val;
        
        //保证了root的左子树的最大值小于root的值并且root的右子树的最小值大于root的值;
        if(min != null && min >= val) return false;//只要root的左子树中有值大于root,就不是BFT;
        if(max != null && max <= val) return false;//只要root的右子树中有值小于root,就不是BFT;
        
        //保证了root的所有左子树和右子树都是BFT;
        if(!help(root.left,min,val)) return false;//在遍历左子树的时候只关心最大值,所以将val赋给max;
        if(!help(root.right,val,max)) return false;//在遍历右子树的时候只关心最小值,所以将val赋给min;
    
        return true;
    }
    public boolean isValidBST(TreeNode root) {
        if(root == null ) return true;
        return help(root,null,null);
    }
 
}

75/75 casos de prueba aprobados
Estado: Aprobado Tiempo de
ejecución: 0 ms
Consumo de memoria: 39,7 MB

Árbol binario simétrico

Dado un árbol binario, compruebe si es simétrico en espejo.
Por ejemplo, el árbol binario [1,2,2,3,4,4,3] es simétrico.

    1
   / \
  2   2
 / \ / \
3  4 4  3

Pero lo siguiente [1,2,2, null, 3, null, 3] no es simetría especular:

    1
   / \
  2   2
   \   \
   3    3

Avanzado:
¿Puede utilizar la recursividad y la iteración para resolver este problema?

Recursión: Dos punteros van a los lados izquierdo y derecho respectivamente, y se comparan el puntero izquierdo y el puntero derecho, de hecho, se comparan el nodo izquierdo y el nodo derecho del subárbol derecho y el subárbol izquierdo.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;
        return check(root.left,root.right);
    }
    
    private boolean check(TreeNode p,TreeNode q) {
        if(p == null && q == null) return true;
         if(p == null || q == null) return false;
        return p.val == q.val && check(p.left,q.right) && check(p.right,q.left);
    }
}

195/195 casos de prueba aprobados
Estado: Aprobado Tiempo de
ejecución: 0 ms
Consumo de memoria: 37,7 MB

Iteración: Uno a uno agregando continuamente a la cola y eliminando la comparación. También es una comparación de los subárboles izquierdo y derecho.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    public boolean isSymmetric(TreeNode root) {
        if(root == null) return true;
    
        return check(root.left,root.right);
    }
    
    public boolean check(TreeNode u, TreeNode v) {
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        q.offer(u);
        q.offer(v);
        while (!q.isEmpty()) {
            u = q.poll();
            v = q.poll();
            if (u == null && v == null) {
                continue;
            }
            if ((u == null || v == null) || (u.val != v.val)) {
                return false;
            }

            q.offer(u.left);
            q.offer(v.right);

            q.offer(u.right);
            q.offer(v.left);
        }
        return true;
    }
}

195/195 casos de prueba aprobados
Estado: Aprobado Tiempo de
ejecución: 1 ms
Consumo de memoria: 39,3 MB

Recorrido de secuencia del árbol binario

Darle un árbol binario, devuelva el valor del nodo obtenido atravesándolo en orden. (Es decir, visite todos los nodos capa por capa, de izquierda a derecha).

Ejemplo:
árbol binario: [3,9,20, null, null, 15,7],

    3
   / \
  9  20
    /  \
   15   7

Devuelve el resultado de su recorrido de nivel:

[
  [3],
  [9,20],
  [15,7]
]

Profundidad primero

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {

    List<List<Integer>> lists = new ArrayList<>();

    public List<List<Integer>> levelOrder(TreeNode root) {
        if(root == null) return lists;
        help(root,0);
        return lists;
    }

    private void help(TreeNode node,int level){
   		//只有列表大小为当前level时新创建一个数组塞进去,这样其他的相同层级就避免多创建
        if(lists.size() == level) {
            lists.add(new ArrayList<Integer>());
        }
        //把node值添加到当前层级数组中
        lists.get(level).add(node.val);
        
		//递归root左侧下一个层级
        if(node.left != null){
            help(node.left,level + 1);
        }
        //递归root右侧侧下一个层级
         if(node.right != null){
             help(node.right,level + 1);
         }
    }
}

34/34 casos de prueba aprobados
Estado: Aprobado Tiempo de
ejecución: 1 ms
Consumo de memoria: 40,3 MB

Esta estrategia de profundidad primero y enfoque de amplitud primero son un poco más complicadas de entender.

Primero ancho

public List<List<Integer>> levelOrder(TreeNode root) {
           //思路 二叉树的层序遍历 通用思路为使用 队列,利用队列先进先出特点保存每一行的结点,遍历之后出队
           //时间复杂度 空间复杂度 O(n)
           List<List<Integer>> res = new ArrayList<>();

           if(root == null){
              return res;
           }
           //存储没层结点队列
           Queue<TreeNode> queueNodes = new LinkedList<>();
           //把当前根节点加入队列
           queueNodes.add(root);

           //遍历队列节点
           while(!queueNodes.isEmpty()){
               //获取当前层级有多少个节点
               int count = queueNodes.size();
               //保存当前遍历节点值得 list
               List<Integer> temp = new ArrayList<>();
               //根据队列中的数据 遍历获取节点值
               for (int i = 0; i < count; i++) {
                   //当前节点是否有左右子节点
                   if(queueNodes.peek().left !=null){
                     queueNodes.offer(queueNodes.peek().left);
                   }
                   if(queueNodes.peek().right !=null){
                    queueNodes.offer(queueNodes.peek().right);
                  }
                  //保存当前节点行元素值数组 并从队列中删除
                  temp.add(queueNodes.poll().val);
               }
               //保存每一层节点数组
               res.add(temp);
           }

            return res;
    }
}
Convierta una matriz ordenada en un árbol de búsqueda binario

Convierta una matriz ordenada en orden ascendente en un árbol de búsqueda binario altamente equilibrado.

En esta pregunta, un árbol binario altamente equilibrado significa que el valor absoluto de la diferencia de altura entre los subárboles izquierdo y derecho de cada nodo de un árbol binario no excede 1.

Ejemplo:

Dada una matriz ordenada: [-10, -3,0,5,9],

Una posible respuesta es: [0, -3,9, -10, nulo, 5], que puede representar el siguiente árbol de búsqueda binaria altamente equilibrado:

      0
     / \
   -3   9
   /   /
 -10  5

La idea fue correcta al principio, pero no fue correcto encontrar la ubicación y el límite.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return  help(nums,0,nums.length - 1);
    }

    private TreeNode help(int[] nums,int left,int right){
        
        if(left > right) return null;

        int mid = (left + right)/2;

        TreeNode root = new TreeNode(nums[mid]);

        root.left = help(nums,left,mid - 1);
        root.right = help(nums,mid + 1, right);
        return root;
    }
}

32/32 casos de prueba aprobados
Estado: Aprobado Tiempo de
ejecución: 0 ms
Consumo de memoria: 39,6 MB

Supongo que te gusta

Origin blog.csdn.net/u011148116/article/details/107212165
Recomendado
Clasificación