permutations de BST

voix
5

Étant donné un tableau d'entiers arr = [5,6,1].

Lorsque nous construisons un BST avec cette entrée dans le même ordre, nous aurons « 5 » en tant que root, « 6 » que l'enfant droit et « 1 » comme enfant gauche.

Maintenant, si notre entrée est changée en [5,1,6], encore notre structure de BST sera identique.

Donc, étant donné un tableau d'entiers, comment trouver le nombre de permutations différentes du tableau d'entrée qui se traduit par la BST identique à celle du BST formé sur l'ordre du tableau original?

Créé 09/11/2009 à 16:07
source utilisateur
Dans d'autres langues...                            


4 réponses

voix
-1

Vous pouvez le faire en arrière: Étant donné un BST, énumérer tous les tableaux d'entiers qui pourraient générer ce BST ...

Impossible de vous (à l'aide ... non-déterminisme)

  1. émettre la racine et l'ajouter à l'ensemble émis.
  2. choisir un élément de non-déterministe de l'arbre qui est pas dans l'ensemble émis, mais dont le parent est, et l'ajouter à l'ensemble émis et émettre.
  3. répéter 2 jusqu'à ce que tous émis.

Le non-déterminisme vous donnera tous ces tableaux. Ensuite, vous pouvez les compter.

Créé 09/11/2009 à 16:15
source utilisateur

voix
9

Votre question est équivalente à la question de compter le nombre de ordonnancements topologiques pour la BST donnée.

Par exemple, pour la BST

  10
 /  \
5   20
 \7 | \
    15 30

l'ensemble des ordonnancements topologiques peut être compté à la main comme ceci: 10 commence chaque commande. Le nombre d'ordres topologiques pour le sous-arbre en commençant par 20 est égal à deux: (20, 15, 30) et (20, 30, 15). Le sous-arbre à partir de 5 a une seule commande: (5, 7). Ces deux séquences peuvent être entrelacées de manière arbitraire, ce qui conduit à 2 x 10 entrelacements, produisant ainsi vingt entrées qui produisent le même BST. Le premier 10 sont énumérés ci-dessous pour le cas (20, 15, 30):

 10 5 7 20 15 30
 10 5 20 7 15 30
 10 5 20 15 7 30
 10 5 20 15 30 7
 10 20 5 7 15 30
 10 20 5 15 7 30
 10 20 5 15 30 7
 10 20 15 5 7 30
 10 20 15 5 30 7
 10 20 15 30 5 7

Le boîtier (20, 30, 15) est analogue --- on peut vérifier que l'une des entrées suivantes de la même produit BST.

Cet exemple fournit également une règle récursive pour calculer le nombre des ordonnancements. Pour une feuille, le nombre est 1. Pour un nœud non-feuille avec un enfant, le nombre est égal au nombre de ordonnancements topologiques pour l'enfant. Pour un nœud non-feuille avec deux enfants avec des tailles de sous-arbre | L | et | R |., les deux ayant l et r ordonnancements, resp, le nombre est égal à

  l x r x INT(|L|, |R|)

Où INT est le nombre de entrelacements possibles | L | et | R | éléments. Cela peut être calculé facilement par (| L | + | R |)! / (| L |! X | R |!). Pour l'exemple ci-dessus, on obtient le calcul récursif suivant:

  Ord(15) = 1
  Ord(30) = 1
  Ord(20) = 1 x 1 x INT(1, 1) = 2  ; INT(1, 1) = 2! / 1 = 2
  Ord(7) = 1
  Ord(5) = 1
  Ord(10) = 1 x 2 x INT(2, 3) = 2 x 5! / (2! x 3!) = 2 x 120 / 12 = 2 x 10 = 20

Cela résout le problème.

Remarque: cette solution suppose que tous les nœuds du BST clés ont différentes.

Créé 10/11/2009 à 18:34
source utilisateur

voix
1

Merci pour l'explication antti.huima! Cela m'a aidé à comprendre. Voici quelques C ++:

#include <vector>
#include <iostream>

using namespace std;

int factorial(int x) {
  return (x <= 1) ? 1 : x * factorial(x - 1);
}

int f(int a, int b) {
  return factorial(a + b) / (factorial(a) * factorial(b));
}

template <typename T>
int n(vector<T>& P) {
  if (P.size() <= 1) return 1;
  vector<T> L, R;
  for (int i = 1; i < P.size(); i++) {
    if (P[i] < P[0])
      L.push_back(P[i]);
    else
      R.push_back(P[i]);
  }
  return n(L) * n(R) * f(L.size(), R.size());
}

int main(int argc, char *argv[]) {
  vector<int> a = { 10, 5, 7, 20, 15, 30 };
  cout << n(a) << endl;
  return 0;
}
Créé 06/03/2013 à 03:59
source utilisateur

voix
0

Cette question peut être résolu facilement si vous avez peu de connaissances de récursivité, permutation et combinaisons, et la familiarité avec Binary arbre de recherche (évidemment).

D'abord, vous construisez un arbre de recherche binaire avec la séquence donnée. Vous pouvez également effectuer la même opération dans le tableau, mais la visualisation d'arbres peindraient une bonne image.

Pour arr séquence donnée [1..n], 1er élément resterait mis comme dans le tableau donné et seul arrangement doit être apporté dans [2..n] arr.

Assumer:

bag1 = nombre d'éléments dans [] 2..n arr qui sont inférieures arr [0].

et,

bag2 = nombre d'éléments dans [] 2..n arr qui sont supérieures arr [0].

Étant donné que la permutation des éléments bag1 dans la séquence ne présente pas de conflit avec les numéros présents dans le bag2 tout en formant un arbre de recherche binaire, on peut commencer à commencer à calculer la réponse en la cueillette des éléments Bag1 sur (n-1) éléments permutent et reposer ensuite ((n-1) - bag1) = éléments de BAG2 peuvent être placés dans une manière que maintenant . Commande d'éléments bag1 doit doit être identique et de même pour les éléments de BAG2 dans la séquence.

Étant donné que chaque sous-arbre d'un arbre de recherche binaire doit être un BST. procédé similaire sera utilisé sur chaque nœud et multiplier la réponse locale pour le noeud de réponse finale.

int ans = 1;
int size[1000000] = {0};

// calculate the size of tree and its subtrees before running function "fun" given below.
int calSize(struct node* root){
     if(root == NULL)
          return 0;

     int l = calSize(root->left);
     int r = calSize(root -> right);
     size[root->val] = l+r+1;
     return size[root->val]; 
}

void fun(struct node* root){
     if(root == NULL)
         return;

     int n = size[root->val];
     if(root->left){
         ans *= nCr(n-1, size[root->left]);
         ans *= 1; // (Just to understand that there is now only 1 way 
                   //to distribute the rest (n-1)-size of root->left)
     }

     fun(root->left);
     fun(root->right); 
}

int main(){
     struct node* root;

     //construct tree
     //and send the root to function "fun"

     fun(root);

     cout<<ans<<endl;
     return 0;
}
Créé 12/08/2017 à 08:52
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more