[Pila] [código de leet] [Medio] 331. Verifique la serialización de preorden del árbol binario

tema:

Una forma de serializar un árbol binario es utilizar el recorrido de preorden. Cuando nos encontramos con un nodo no vacío, podemos registrar el valor de este nodo. Si es un nodo vacío, podemos usar un registro de valor de etiqueta, como #.


Por ejemplo, el árbol binario anterior se puede serializar en la cadena "9,3,4, #, #, 1, #, #, 2, #, 6, #, #", donde # representa un nodo vacío.

Dada una secuencia separada por comas, verifique que sea la serialización de preorden correcta del árbol binario. Escribe un algoritmo factible sin reconstruir el árbol.

Cada carácter separado por comas es un número entero o un '#' que representa un puntero nulo.

Puede pensar que el formato de entrada siempre es válido, por ejemplo, nunca contendrá dos comas consecutivas, como "1,, 3".

fuente:

331. Verificar la serialización de preorden del árbol binario

Idea de resolución de problemas 1: apilar

Después de leer la pregunta, estaba un poco confundido. Miré los ejemplos de la pregunta con atención y descubrí que # son todos nodos de hoja y que los números son todos nodos que no son de hoja.

La idea de determinación es la siguiente: #Tira de la pila, empuja el número

Defina una pila para almacenar el número de hijos de un nodo digital El nodo digital debe tener 2 hijos. Bucle todos los nodos:

  • Cuando el nodo es #, la pila termina si está vacía; de lo contrario, se agrega un elemento secundario al elemento superior de la pila;
  • Cuando el nodo es un número, si la pila está vacía, se enviará directamente a la pila; de lo contrario, se enviará a la pila después de agregar un hijo al elemento superior de la pila;
  • Cuando el nodo superior de la pila ha satisfecho a 2 niños, la pila se abre hasta que está vacía o el nodo superior de la pila no es suficiente para 2 niños.

Cuando la pila está vacía y no hay ningún nodo detrás, devuelve verdadero, otro falso.

El código es el siguiente (un poco confuso):

class Solution {
public:
    bool isValidSerialization(string preorder) {
        stack<int> st;
        int i = 0;
        while (i < preorder.size()) {
            char ch = preorder[i];
            while (i < preorder.size() && preorder[i] != ',') i++;
            i++;

            if (ch == '#') {
                if (st.empty()) break;
                // top++
                int t = st.top();
                st.pop();
                st.push(t+1);
            } else {
                // top++
                if (!st.empty()) {
                    int t = st.top();
                    st.pop();
                    st.push(t+1);
                }
                st.push(0);
            }
            bool end = false;
            while (st.top() == 2) {
                st.pop();
                if (st.empty()) {
                    end = true;
                    break;
                }
            }
            if (end) break;
        }
        return st.empty() && i >= preorder.size();
    }
};

Idea de resolución de problemas 2: utilizar la naturaleza de los nodos

Cada nodo no hoja debe tener 2 hijos, por lo que debe satisfacerse: el nodo hoja debe tener uno más que el nodo no hoja. En esta pregunta, #node es 1 más que un número de nodo.

Escribir código basado en esta naturaleza es simple: defina el recuento cnt = 1, cuando # es -, cuando el número es ++, y cuando el recuento es 0, salga, y después de salir, juzgue si hay nodos en el futuro.

int isValidSerialization(char * preorder){
    int cnt = 1;
    char *p = preorder;
    while (*p != 0) {
        if (*p == '#') {
            cnt--;
        } else {
            cnt++;
        }
        while (*p != 0 && *p != ',') p++;
        if (*p == ',') p++;

        if (cnt == 0) break;
    }

    return cnt == 0 && *p == 0;
}

 

Supongo que te gusta

Origin blog.csdn.net/hbuxiaoshe/article/details/114695571
Recomendado
Clasificación