¿Cuál es el mejor método para verificar si un árbol binario es un árbol de búsqueda binario?

Esto se puede resolver de 2 maneras:

Método 1:

1. Encuentre el valor máximo en el subárbol izquierdo de la raíz. Si es mayor que root, devuelve falso.

2. Encuentre el valor mínimo en el subárbol derecho de la raíz. Si es menor que root, devuelve falso.

3. Verifique recursivamente lo mismo para los subárboles izquierdo y derecho.

Complejidad del tiempo: O (n ^ 2)

Método 2:

En un BST, la raíz es mayor que todos los nodos del subárbol izquierdo. Entonces, el valor raíz forma un límite superior en los valores del subárbol izquierdo.

De manera similar, dado que la raíz es menor que todos los nodos del subárbol derecho, el valor raíz forma un límite inferior en los valores del subárbol derecho.

Esto se puede usar para verificar si un árbol binario es un árbol de búsqueda binario o no.

1. Inicializar, bajo = MIN_VALUE, alto = MAX_VALUE.

2. Si root.data = high, devuelve false.

3. Verifique recursivamente el subárbol izquierdo y el subárbol derecho.

a. Para el subárbol izquierdo, pase alto como root.data porque para un BST, la raíz forma un límite superior para los valores del nodo del subárbol izquierdo.

si. Para el subárbol derecho, pase bajo como root.data porque para un BST, la raíz forma un límite inferior para los valores del nodo del subárbol derecho.

Complejidad del tiempo: O (n)

public boolean isBinarySearchTree () {
return isBinarySearchTree (root, Integer.MIN_VALUE, Integer.MAX_VALUE);
}

private boolean isBinarySearchTree (raíz del nodo, int low, int high) {
if (root == null) {
volver verdadero;
}
if (root.data = alto) {
falso retorno;
}
return isBinarySearchTree (root.left, low, root.data) &&
isBinarySearchTree (root.right, root.data, high);
}

Fuente: Compruebe si un árbol binario es un árbol de búsqueda binario

Lo mejor es difícil de definir en este caso. Ningún algoritmo puede ser más rápido que O (n)

Creo que lo más simple es hacer un recorrido en orden (izquierda, raíz, derecha) y confirmar que el resultado está ordenado.

Alternativamente, podemos recordar los valores críticos para un nodo a medida que avanzamos hacia abajo (este algo es bueno porque no requiere memoria adicional aunque a costa del espacio de pila log (n))

Me gusta el algoritmo recursivo simple:

boolean isBST (BinaryNode n)
{
return isBST (n, T.MIN_VALUE, T.MAX_VALUE);
}

boolean isBST (BinaryNode n, T min, T max) {
if (! (n.value <= n.right.value && n.value> = n.left.value && n.value> = min && n.value <= max)) {
falso retorno;
}
return isBST (n.left, min, n.value) && isBST (n.right, n.value, max)
}

Para cualquier nodo dado, debemos verificar que esté entre sus hijos no mayor que su padre derecho más pequeño o más pequeño que su padre izquierdo más grande.

Si T es comparable y no dice Entero, cambiamos el <= y> = con el .compareTo apropiado (o el equivalente de su lenguaje) y encontramos los elementos más a la derecha e izquierda en el árbol como nuestro máximo y mínimo respectivamente para la llamada inicial. El tiempo total sigue siendo O (n)

  • Propiedad: Un árbol binario es un Árbol de búsqueda binaria cuando todos los elementos a la izquierda son menores que el nodo actual y los de la derecha son mayores que ese nodo.
  • Entonces, la forma más simple de entender es que cuando imprime un nodo izquierdo, raíz y nodo derecho, debe obtener una lista ordenada basada en la propiedad de BST.
  • En otras palabras, atravesar en el orden Izquierda, Raíz, Derecha se llama Recorrido transversal.
  • El recorrido en orden visita cada elemento de un árbol exactamente una vez y, por lo tanto, toma O (n) tiempo, donde ‘n’ es el número de elementos.

  • Por lo tanto, si el recorrido Inorder de un árbol Binario produce una lista ordenada, entonces se dice que el árbol es un Árbol de Búsqueda Binaria.

Solicite el valor máximo en el subárbol izquierdo y el mínimo en el subárbol derecho y verifique si los valores raíz se encuentran entre ambos, haga recursivamente para todos los nodos

int isBST (nodo de estructura * nodo)
{
if (nodo == NULL)
retorno (verdadero);

/ * falso si el máximo de la izquierda es> que nosotros * /
if (nodo-> izquierda! = NULL && maxValue (nodo-> izquierda)> nodo-> datos)
falso retorno);

/ * falso si el mínimo de la derecha es <= que nosotros * /
if (nodo-> derecho! = NULL && minValue (nodo-> derecho) datos)
falso retorno);

/ * falso si, recursivamente, la izquierda o la derecha no es un BST * /
if (! isBST (nodo-> izquierda) ||! isBST (nodo-> derecha))
falso retorno);

/ * pasando todo eso, es un BST * /
retorno (verdadero);
}

Un árbol binario es solo una estructura de datos donde cada nodo tiene hasta dos hojas.

5 5
/ \
6 9
/ \ / \
10 4 11 7

Un árbol de búsqueda binario es un árbol binario donde para cada nodo todos los nodos a la izquierda son menores que su valor y todos los nodos a la derecha son mayores que su valor

7 7
/ \
5 10
/ \ / \
4 6 9 11
y no hay nodos duplicados.

Inicialmente podría pensar que si atraviesa el árbol y para cada nodo, la izquierda es menor y la derecha mayor que el nodo actual, pero eso no funciona. Si bien esto ha dejado nodos parent, no es un BST porque 8 no es menor que 7.

7 7
/ \
5 10
/ \ / \
4 8 9 11

En su lugar, debe tratar cada nodo como un árbol y verificar. Esto es más fácil a través de la recursividad:

typedef struct _node {
int value;
struct _node *left;
struct _node *right
} Node; int notSearchable=0; int isSearchable(Node node, int max, int min)
{
// Is this a leaf?
if (node == null)
return(true); // unwind recursion // Check versus our stored range
if (notSearchable || node->value >= max || node->value <= min) {
notSearchable=1;
return false;
} // Check the sub-tree
return (isSearchable(node->left, node->value, min) &&
isSearchable(node->right, max, node->value));
}

typedef struct _node {
int value;
struct _node *left;
struct _node *right
} Node; int notSearchable=0; int isSearchable(Node node, int max, int min)
{
// Is this a leaf?
if (node == null)
return(true); // unwind recursion // Check versus our stored range
if (notSearchable || node->value >= max || node->value <= min) {
notSearchable=1;
return false;
} // Check the sub-tree
return (isSearchable(node->left, node->value, min) &&
isSearchable(node->right, max, node->value));
}

typedef struct _node {
int value;
struct _node *left;
struct _node *right
} Node; int notSearchable=0; int isSearchable(Node node, int max, int min)
{
// Is this a leaf?
if (node == null)
return(true); // unwind recursion // Check versus our stored range
if (notSearchable || node->value >= max || node->value <= min) {
notSearchable=1;
return false;
} // Check the sub-tree
return (isSearchable(node->left, node->value, min) &&
isSearchable(node->right, max, node->value));
}

typedef struct _node {
int value;
struct _node *left;
struct _node *right
} Node; int notSearchable=0; int isSearchable(Node node, int max, int min)
{
// Is this a leaf?
if (node == null)
return(true); // unwind recursion // Check versus our stored range
if (notSearchable || node->value >= max || node->value <= min) {
notSearchable=1;
return false;
} // Check the sub-tree
return (isSearchable(node->left, node->value, min) &&
isSearchable(node->right, max, node->value));
}

typedef struct _node {
int value;
struct _node *left;
struct _node *right
} Node; int notSearchable=0; int isSearchable(Node node, int max, int min)
{
// Is this a leaf?
if (node == null)
return(true); // unwind recursion // Check versus our stored range
if (notSearchable || node->value >= max || node->value <= min) {
notSearchable=1;
return false;
} // Check the sub-tree
return (isSearchable(node->left, node->value, min) &&
isSearchable(node->right, max, node->value));
}

Si a su profesor no le gustan las variables globales, simplemente elimine todas las referencias a notSearchable , seguirá funcionando, pero no es la forma más rápida de hacerlo.

Hay muchas maneras de verificar si Binary Tree es BST o no, una de las cuales es más fácil y eficiente, lo sé:

Atraviese el árbol en forma ordenada (es decir: Izquierda-> imprimir (Nodo) -> Derecha) y almacene los elementos en una matriz en lugar de imprimirlos. Finalmente, después de completar el recorrido, verifique si su matriz está ordenada en orden ascendente o no. Si está ordenado, ¡Holaaa! ya terminaste con eso.

PD: el recorrido en orden siempre se imprime en orden ascendente.

Respondiendo esto, ya que me lo pidieron. Espero que ya sepas cuál es la diferencia. Si sabes, entonces esto no será difícil.

Cuando dice método, ¿quiere decir que necesita una función programable? Agregar detalles a la pregunta siempre facilita la respuesta.

Es posible que desee hacer referencia a esto: diferencia entre el árbol binario y el árbol de búsqueda binaria

También tiene la función definida en las respuestas.

Árbol binario: cada nodo tiene dos hijos.
Árbol binario de búsqueda: para cada nodo, mayor que el hijo izquierdo y menor que el hijo derecho.

Un árbol no es un árbol de búsqueda binario si alguna rama no satisface la demanda. Entonces tenemos que atravesar todos los nodos.

Pseudocódigo aproximado:

bool IsBinarySearchTree (Nodo * p):
si p == nulo:
volver verdadero
si p.izquierda> p || p.right falso retorno
if! IsBinarySearchTree (p.left) || ! IsBinarySearchTree (p.right):
falso retorno
volver verdadero

Editado:
Todo lo anterior no está bien, vea el comentario de Justin Rising, hay una buena respuesta en Wikipedia:
Esto no funciona Consulte Árbol de búsqueda binaria para ver un ejemplo en el que debe realizar un seguimiento de más información.

Editado:
Mi código mejorado:

(bool válido, int min, int max) IsBinarySearchTree (Nodo * p):
si p == nulo:
devuelve verdadero, p, p
valid1, min1, max1 = IsBinarySearchTree (p.left):
valid2, min2, max2 = IsBinarySearchTree (p.right):
si max1> p || min2

devuelve falso, -1, -1
devuelve verdadero, min1, max2

isValid (raíz del nodo) {return isValidBST (root, Integer.MIN_VALUE, Integer.MAX_VALUE); }

isValidBST (nodo de nodo, int MIN, int MAX) {
if (nodo == nulo)
volver verdadero;
if (node.value> MIN && node.value de lo contrario devuelve falso; }

Complejidad del tiempo: O (n)

Hay varias formas

Método 1- Use el recorrido en orden y almacene los datos en una matriz. Compruebe si la matriz está ordenada o no

Complejidad de tiempo y espacio – O (n)

Método 2: tome una variable y asigne su valor INT_MIN, use en orden transversal si encuentra que el valor del nodo izquierdo es más pequeño que su valor raíz, luego actualice la raíz con el nodo izquierdo y para el nodo derecho simplemente verifique si el valor es mayor o no .

Complejidad de tiempo- O (n)

Complejidad espacial- O (1)

**¡Espero que esto te ayudará!.

Para cada nodo x, calcula recursivamente los siguientes valores:
M [x] = max (tecla [x], M [izquierda [x]], M [derecha [x]])
m [x] = min (tecla [x], m [izquierda [x], m [derecha [x]])
(M es la clave máxima en el subárbol de x, m es la clave mínima en el subárbol de x)

Entonces, si lo siguiente se cumple para cada nodo x:
M [izquierda [x]] Es un árbol de búsqueda binario (bueno, suponiendo que todas las claves sean distintas).
La complejidad es O (n).

Un recorrido en orden para verificar que el nodo actual es más grande que el anterior tiene una implementación obvia de los principios básicos y se ejecuta en tiempo lineal.

static bool checkBSTInternal (const Node ** anterior,
const Node * current) {
bool ret;
if (! current) {
ret = verdadero;
} más {
ret = checkBSTInternal (anterior, actual-> izquierda) &&
(! * prev || (* prev) -> data data);
* prev = actual;
ret & = checkBSTInternal (anterior, actual-> derecha);
}
volver ret;
}

bool checkBST (Nodo * raíz) {
const Node * prev = NULL;
return checkBSTInternal (& prev, root);
}

Prefiero usar Java, por lo que mi respuesta refleja mi preferencia de lenguaje. Mi solución a esto sería:


isBST privado booleano () {
return isBST (raíz, nulo, nulo);
}

isBST booleano privado (Nodo x, Clave mín., Clave máx.) {
si (x == nulo)
volver verdadero;
if (min! = nulo && x.key. compareTo (min) <= 0)
falso retorno;
if (max! = nulo && x.key. compareTo (max)> = 0)
falso retorno;
return isBST (x.left, min, x.key) && isBST (x.right, x.key, max);
}


Puede comenzar con la definición de un árbol de búsqueda binario. En un BST, cada nodo tiene un hijo izquierdo y derecho. El niño izquierdo debe ser menor o igual que el padre y el niño derecho debe ser estrictamente mayor que el padre.

Ahora para el algoritmo. Para cada nodo padre, verifique si el hijo izquierdo es menor o igual que el padre y si el nodo derecho es mayor que el padre. Lo hace de forma recursiva hasta que haya visitado todos los nodos del árbol. El truco consiste en pasar correctamente el valor mínimo y máximo que puede tener un nodo cuando realiza la llamada recursiva.

Verifique que tenga la propiedad del árbol de búsqueda binaria. Es decir, el subárbol izquierdo debe tener valores <= el valor en la raíz, que a su vez debe tener valores <= valores del subárbol derecho. Un algoritmo recursivo servirá.

Un método diferente es realizar un recorrido en orden y almacenar los elementos en una matriz. Una vez hecho, verifique que la matriz esté ordenada.

Ambos algoritmos toman tiempo lineal.

El punto básico es:

Todos los nodos en el subárbol izquierdo <= nodo raíz <= todos los nodos en el subárbol derecho. Y esta propiedad debe mantenerse en cada subárbol, lo que implica una comprobación recursiva de esta propiedad al considerar cada nodo interno como la raíz de un subárbol.

Este enfoque nos brinda el siguiente algoritmo de fuerza bruta:

boolean isBST (raíz de TreeNode)
{
if (raíz == nulo)
volver verdadero;

// verifica todos los nodos a la izquierda <= root <= todos los nodos a la derecha
boolean ret = isBSTHelper (root.left, root, root.right);

// ahora repita esto para cada nodo / subárbol.
si (ret == verdadero)
{
return isBST (root.left) && isBST (root.right);
}

falso retorno;
}

boolean isBSTHelper (TreeNode lnode, TreeNode root, TreeNode rnode)
{
izquierda booleana = falso;
derecho booleano = falso;

if (lnode! = nulo)
{
if (lnode.data> root.data)
falso retorno;

left = isBSTHelper (lnode.left, lnode, lnode.right);
}
más
{
izquierda = verdadero;
}

if (rnode! = null)
{
if (rnode.data falso retorno;

right = isBSTHelper (rnode.left, rnode, rnode.right);
}
más
{
derecho = verdadero;
}

volver a la izquierda y derecha;
}

La complejidad del algoritmo anterior es O (n ^ 2) ya que estamos tocando cada nodo varias veces: cada subárbol se evalúa varias veces.

isBSTHelper () busca una raíz determinada:

todos los nodos en el subárbol izquierdo <= raíz <= todos los nodos en el subárbol derecho

Y, isBST () repite esta operación de forma recursiva para cada nodo del árbol. Por lo tanto, varias veces se evalúa un subárbol o un nodo.

Podemos hacer esto en O (n) de la siguiente manera:

Cada vez que recurrimos al subárbol izquierdo, sabemos qué límite máximo / superior debemos obedecer: este es el valor raíz.

Cada vez que recurrimos al subárbol derecho, sabemos qué límite mínimo / inferior debemos obedecer; este es nuevamente el valor raíz.

Por lo tanto, a medida que seguimos recurriendo hacia abajo en el árbol, cambie los valores mínimo y máximo y de esta manera habríamos agotado todo el árbol al tocar cada nodo exactamente una vez.

boolean isBST (raíz de TreeNode)
{
if (raíz == nulo)
volver verdadero;

return isBSTHelper (root, Integer.MIN_VALUE, Integer.MAX_VALUE);
}

boolean isBSTHelper (raíz de TreeNode, int min, int max)
{
if (raíz == nulo)
volver verdadero;

if (min <= root.data && root.data <= max)
{
return isBSTHelper (root.left, min, root.data)
&&
isBSTHelper (root.right, root.data, max);
}

falso retorno;
}

Lo anterior es un enfoque O (n).

Esta solución es válida asumiendo que todos los elementos en BST son únicos.
Realice un recorrido en orden del árbol y almacene cada elemento en una matriz durante el recorrido en orden. Ahora verifique si esta matriz está ordenada.
En orden (i, T)
{
si (T! = nulo) {
En orden (i, izquierda (T));
Matriz [i] = valor (T);
En orden (i + 1, derecha (T))
}
}

checkArray (matriz)
{
para (i = 0; i {
if (matriz [i]> matriz [i + 1])
falso retorno;
}
volver verdadero;
}

La complejidad del tiempo para esto será O (n). Como el recorrido en orden toma solo O (n) tiempo y también lo hace el recorrido de la matriz.

Una solución más generalizada se puede ver aquí:
http://en.wikipedia.org/wiki/Bin

Esta es una de las preguntas sobre el árbol de búsqueda binaria que usualmente cometemos errores y escribimos código incorrecto. Por lo general, nos centramos en el nodo actual y sus elementos secundarios mientras verificamos la propiedad del árbol de búsqueda binaria que conduce a una respuesta incorrecta.
Hay tres formas en que se puede verificar un árbol binario para el árbol de búsqueda binaria
1. En este método, verificamos cada nodo con el máximo en el subárbol izquierdo y el mínimo en el subárbol derecho. El nodo debe ser mayor que el máximo y debe ser menor que el mínimo. Si cada nodo sigue esto, entonces el árbol es un árbol de búsqueda binario. Este método tiene una complejidad temporal de O (n2).

2. El segundo método consiste en limitar el rango en el que caen los elementos en el lado izquierdo y derecho del nodo. En el lado izquierdo, los nodos pueden tener cualquier valor mínimo, pero el valor máximo debe ser el valor del nodo. Del mismo modo, todos los nodos en el lado derecho pueden tener cualquier valor máximo, pero el valor mínimo debe ser mayor o igual que el valor del nodo. La complejidad de este método es O (n) ya que atravesaremos cada nodo solo una vez y pasaremos max y min.

3. El tercer método consiste en hacer un recorrido transversal del árbol y verificar si el recorrido está ordenado o no. O bien almacenamos el recorrido en una matriz con una complejidad espacial de O (n) o podemos verificar el valor anterior mientras que el recorrido siempre debe ser menor que el valor del nodo actual para que la salida esté ordenada. La complejidad es nuevamente O (n).

Lo he explicado en mi blog, también puedes ver videos.
¿Verifica si el árbol binario es Binary Search Tree (BST) o no?

def checkIfBST (self, rootNode):
si rootNode == Ninguno:
volver verdadero
if rootNode.left! = None y rootNode.data falso retorno
if rootNode.right! = None y rootNode.data> rootNode.right.data:
falso retorno
si no self.checkIfBST (rootNode.left) y no self.checkIfBST (rootNode.right):
falso retorno
volver verdadero

Un DFS simple (búsqueda en profundidad) que se aplica a todos los nodos del árbol O (N), mientras se compara si algún nodo no está en su lugar.

Devuelva falso si encuentra un nodo fuera de lugar, si no puede encontrar un nodo fuera de lugar, devuelva verdadero que tomará un máximo de O (N)

More Interesting

¿Cuáles son los beneficios de codificar en una pizarra durante una entrevista? ¿Por qué es eso mejor en comparación con la codificación en un IDE?

¿Por qué las entrevistas de programación a menudo implican preguntas que solo se pueden resolver de manera eficiente utilizando algún algoritmo de conocimiento previo?

¿Qué preguntas has encontrado durante una entrevista de desarrollador iOS?

¿Cómo debería (un estudiante de tercer año de ingeniería informática) mejorar mis posibilidades de entrevistas de prácticas?

Se le da una matriz de n elementos [1,2, ... .n]. Por ejemplo {3,2,1,6,7,4,5}. Ahora creamos una firma de esta matriz comparando cada par de elementos consecutivos. Si aumentan, escriba I else write D.?

¿Hay alguna diferencia entre las preguntas de la entrevista telefónica de Google y las preguntas de la entrevista en el sitio, para un puesto de SDE?

Cómo prepararse para una entrevista de colocación de Informatica

Cómo prepararse para una entrevista Java con 15 meses de experiencia

¿Es un factor decisivo que, durante mis entrevistas en Google, cuando terminé de resolver un problema, el tiempo casi había terminado y el entrevistador no podía hacerme una segunda pregunta?

¿Cómo se puede estar bien preparado para responder preguntas sobre estructura de datos / algoritmos en entrevistas?

¿Cuáles son algunas de las preguntas técnicas en la entrevista de Facebook?

¿Qué es la entrevista de codificación?

Dada una lista de 'n' palabras, verifique si forman una cadena de palabras. En una cadena de palabras, las palabras adyacentes deben diferir exactamente en una letra, por ejemplo, ¿curar, cabeza, muerto, escritura, ciervo, cerveza?

¿Son fáciles las entrevistas de programación?

Programación dinámica (DP): dos jugadores juegan el siguiente juego: eligen un número aleatorio N (menos de 2 mil millones) y luego, a partir de 1, se turnan para multiplicar el número del turno anterior con 2 o 9 (su elección). Quien llegue a N primero gana. ¿Determinar ganador del juego de números 2/9?