permutacje BST

głosy
5

Biorąc pod uwagę wartości całkowitych arr = [5,6,1].

Kiedy budujemy BST z tego wejścia w takiej samej kolejności, będziemy mieli „5” jako root, „6” jako prawe dziecko i „1” jako lewy dziecka.

Teraz, jeśli nasz wkład zostanie zmieniona na [5,1,6], jeszcze nasza struktura BST będą identyczne.

Tak więc biorąc pod uwagę tablicę liczb całkowitych, jak znaleźć wiele różnych permutacji tablicy wejściowej, która prowadzi do identycznego jak BST BST utworzonej na oryginalnej kolejności tablicy?

Utwórz 09/11/2009 o 16:07
źródło użytkownik
W innych językach...                            


4 odpowiedzi

głosy
-1

Można to zrobić w tył: Biorąc pod uwagę BST, wyliczyć wszystkie tablice liczb całkowitych, które mogłyby dają ten BST ...

nie mogłeś (używając nondeterminism ...)

  1. emitują korzeń i dodać go do wysyłanego zestawu.
  2. niedeterministycznie wybrać pozycję z drzewa, który nie jest w zestawie, ale emitowanego którego rodzic jest i dodać go do zestawu emitowanego i emitują go.
  3. powtórz 2, aż wszystkie emitowane.

Nondeterminism daje wszystkie takie tablice. Następnie można je policzyć.

Odpowiedział 09/11/2009 o 16:15
źródło użytkownik

głosy
9

Twoje pytanie jest równoważne kwestii liczenia liczby porządków topologicznych dla danego BST.

Na przykład, dla BST

  10
 /  \
5   20
 \7 | \
    15 30

zestaw porządków topologicznych można policzyć ręcznie tak: 10 rozpoczyna każdy zamówieniu. Liczba topologii uporządkowania dla poddrzewem wychodząc z 20 wynosi dwa (20, 15, 30) oraz (20, 30, 15). Poddrzewo wychodząc z 5 ma tylko jeden zamawiania: (5, 7). Te dwie sekwencje mogą być przeplatane w dowolny sposób, co prowadzi do 2 x 10 interleavings, wytwarzając dwadzieścia wejściowe, które wytwarzają taki sam BST. Pierwszy 10 są wymienione poniżej obudowy (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

Przypadek (20, 30, 15) jest analogiczna --- można sprawdzić, że każdy z następujących wejść produkuje taką samą BST.

Przykład ten dostarcza również regułę rekurencyjną aby obliczyć liczbę porządków. Na liściu, liczba wynosi 1. Dla węzeł non-liść z jednym dzieckiem, liczba jest równa liczbie topologicznych porządków dla dziecka. Dla węzła bez liści z dwójką dzieci o rozmiarach SUBTREE | L | i | r |., oba posiadające uporządkowania L i R, odpowiednio, liczba jest równa

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

Gdzie INT jest liczba możliwych interleavings grupy | L | a | R | elementy. To można obliczyć w prosty sposób (| L | + | r |)! / (| L |! X | R |!). Dla powyższego przykładu, otrzymujemy następujące rekurencyjnego obliczenia:

  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

To rozwiązuje problem.

Uwaga: to rozwiązanie zakłada, że ​​wszystkie węzły w BST mają różne klucze.

Odpowiedział 10/11/2009 o 18:34
źródło użytkownik

głosy
1

Dzięki za antti.huima wyjaśnienie! To pomogło mi zrozumieć. Oto niektóre 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;
}
Odpowiedział 06/03/2013 o 03:59
źródło użytkownik

głosy
0

Na to pytanie można łatwo rozwiązać, jeśli masz trochę wiedzy rekursji, permutacji i kombinacji oraz znajomości binarne drzewo poszukiwań (oczywiście).

Najpierw trzeba zbudować wyszukiwanie binarne drzewo z danej sekwencji. Można również wykonać tę samą operację w tablicy, ale drzewa-wizualizacji byłoby namalować dobry obraz.

Dla danej sekwencji arr [1..n], 1 Element będzie pozostawać w miejscu, jak to jest w danym szeregu i tylko układ musi zostać dostosowany arr [2..n].

Założyć:

bag1 = liczba elementów arr [2..n], które są mniejsze niż ARR [0].

i,

bag2 = liczba elementów arr [2..n], które są większe niż ARR [0].

Ponieważ permutacja elementów w bag1 w sekwencji nie będzie stwarzać konfliktu z numerami obecnych w bag2 podczas formowania przeszukiwania binarnego drzewa można rozpocząć rozpocząć obliczenia odpowiedź poprzez zbieranie elementów bag1 z (n-1) Elementy do permutate i spoczywają ((n-1) - bag1) = bag2 elementy mogą być umieszczone w sposób dopiero 1 . Kolejność elementów bag1 powinny powinny być takie same, a także elementów bag2 w sekwencji.

Od każdego poddrzewa poszukiwania binarnego drzewa musi być BST. Podobny proces będzie pracować na każdym węźle i pomnożyć lokalną odpowiedź na węźle do ostatecznej odpowiedzi.

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;
}
Odpowiedział 12/08/2017 o 08:52
źródło użytkownik

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