web-dev-qa-db-fra.com

Recherche si un arbre binaire est un arbre de recherche binaire

Aujourd'hui, j'ai eu une interview où on m'a demandé d'écrire un programme qui prend un arbre binaire et renvoie vrai s'il s'agit également d'un arbre de recherche binaire sinon faux.

Mon approche1: Effectuer une traversée dans l'ordre et stocker les éléments dans O(n) temps. Maintenant, parcourez le tableau/la liste des éléments et vérifiez si l'élément à ie l'indice est supérieur à l'élément en (i + 1)e indice. Si une telle condition est rencontrée, retournez false et sortez de la boucle. (Cela prend O(n) fois). À la fin, retourne true.

Mais ce monsieur voulait que je fournisse une solution efficace. J'ai essayé mais j'ai échoué, car pour savoir s'il s'agit d'un BST, je dois vérifier chaque nœud.

De plus, il me désignait la réflexion sur la récursivité. Mon approche 2: Un BT est un BST si pour n'importe quel nœud N N-> gauche est <N et N-> droite> N, et le successeur dans l'ordre du nœud gauche de N est inférieur à N et le successeur dans l'ordre du nœud droit de N est supérieur à N et les sous-arbres gauche et droit sont des BST.

Mais cela va être compliqué et le temps d'exécution ne semble pas être bon. Aidez-nous si vous connaissez une solution optimale.

33
dharam

C'est un problème assez connu avec la réponse suivante:

public boolean isValid(Node root) {
     return isValidBST(root, Integer.MIN_VALUE,
          Integer.MAX_VALUE);
}
private boolean isValidBST(Node node, int l, int h) {
     if(node == null)
         return true;
     return node.value > l 
         && node.value < h
         && isValidBST(node.left, l, node.value)
         && isValidBST(node.right, node.value, h);
}

L'appel récursif s'assure que les nœuds de sous-arbre sont à la portée de ses ancêtres, ce qui est important. La complexité du temps d'exécution sera O(n) puisque chaque nœud est examiné une fois.

L'autre solution serait de faire un parcours dans l'ordre et de vérifier si la séquence est triée, d'autant plus que vous savez déjà qu'un arbre binaire est fourni en entrée.

78
Dhruv Gairola

La réponse fournie par @Dhruv est bonne. En plus de cela, voici une autre solution qui fonctionne en O(n) temps.
Nous devons garder une trace du nœud précédent dans cette approche. Dans chaque appel récursif, nous vérifions les données du nœud précédent avec les données du nœud actuel. Si les données du nœud actuel sont inférieures aux précédentes, nous renvoyons false

int isBST(node* root) {
  static node* prev  = NULL;

  if(root==NULL)
    return 1;

  if(!isBST(root->left))
    return 0;

  if(prev!=NULL && root->data<=prev->data)
    return 0;

  prev = root;
  return isBST(root->right);
}
7
AgentX
boolean b = new Sample().isBinarySearchTree(n1, Integer.MIN_VALUE, Integer.MAX_VALUE);
.......
.......
.......
public boolean isBinarySearchTree(TreeNode node, int min, int max){
  if(node == null){
    return true;
  }

  boolean left  = isBinarySearchTree(node.getLeft(), min, node.getValue());
  boolean right = isBinarySearchTree(node.getRight(), node.getValue(), max);

  return left && right && (node.getValue()<max) && (node.getValue()>=min);      
}

Les commentaires sont invités. Merci.

1
Trying

Je pense que la deuxième approche est juste. L'arbre peut être parcouru de manière récursive. À chaque itération, les limites inférieures et supérieures du sous-arbre actuel peuvent être stockées. Si nous voulons vérifier le sous-arbre avec la racine x, et les limites du sous-arbre sont l et h, alors tout ce dont nous avons besoin est de vérifier que l <= x <= h et de vérifier le sous-arbre gauche avec les limites l et x, et la droite un avec des bornes x et h.

Cela aura une complexité O(n), car nous partons de la racine et chaque nœud n'est vérifié qu'une seule fois en tant que racine d'un sous-arbre. De plus, nous avons besoin de O(h) mémoire pour les appels récursifs, où h est la hauteur de l'arborescence.

0
fdermishin