Für eine gegebene Binärbaum findet maximalen binären Suchunterbaum

stimmen
13

Für einen binären Baum gegeben, finden Sie den größten Teilbaum, den Baum auch binäre Suche ist?

Beispiel:

Eingang:

                   10
               /         \
             50           150
            /  \         /   \
          25    75     200    20
         / \   / \    /  \    / \
        15 35 65 30  120 135 155 250 

Ausgabe:

                   50
                  /   \
                 25   75
                / \   /
               15 35  65
Veröffentlicht am 02/07/2010 um 06:15
quelle vom benutzer
In anderen Sprachen...                            


7 antworten

stimmen
0

Ein binärer Suchbaum gibt Ihnen ein sortierte Ergebnis, wenn Sie eine IN-ORDER Traversal tun. Also, ein in Ordnung Traversal für den gesamten binären Baum. Die längsten sortierte Folge ist Ihr größter binärer Suchunterbaum.

  • Führen Sie eine Inorder Traversal von Elementen (VISIT LEFT, VISIT ROOT, VISIT RIGHT)
  • Während Dabei die Knotendaten zu erhalten, zu vergleichen, ob die vorherigen Knotendatum als die nächsten Daten kleiner sind. Wenn dem so ist, Inkrementieren Zähler um 1. Speichern der Startknoten.
  • Wenn der Vergleich fehlschlägt, Speichern der Endknoten und Reset-Zähler auf 0
  • Speichern diese Informationen (Zähler, Beginn, Ende) Knoten in einer Arraystruktur später zu finden, die den maximalen Wert aufweist, und das gibt man die längste Unterstruktur Binärsuche
Beantwortet am 02/07/2010 um 06:26
quelle vom benutzer

stimmen
2

Interessante Frage!

Mein früherer Versuch war moronically falsch!

Hier ist ein weiterer Versuch (hoffentlich diesmal korrigieren).

Ich gehe davon aus dem Baum verbunden ist.

Angenommen , für jeden Knoten n des Baumes, Sie hatten eine Reihe von Nachkommen von n, S n mit der Eigenschaft , dass

  • Für jedes Mitglied x von S n , ist der eindeutige Pfad von n bis x ein binärer Suchbaum (es ist nur ein Weg, aber man kann es nach wie vor einen Baum betrachten).

  • Für jeden Abkömmling y von x, so daß der Weg von n bis Y ein BST ist, y in S n .

Der Satz von Knoten S n , gibt Ihnen die größte BST bei n verwurzelt.

Wir können S konstruieren n , indem Sie eine Tiefensuche auf dem Baum, und Weitergabe in der Weginformation (der Pfad von der Wurzel zu dem aktuellen Knoten) und Aktualisieren der Sätze von den Knoten in dem Pfad , der durch Rückverfolgung entlang des Pfades für jeden Knoten.

Wenn wir einen Knoten besuchen, gehen wir den Weg nach oben, und prüfen Sie, ob die BST-Eigenschaft erfüllt ist, für das Segment des Pfades so weit hinaufging. Wenn ja, fügen wir den aktuellen Knoten zu dem entsprechenden Satz des Knotens des Weges, den wir nur gingen. Wir hören auf zu Fuß den Weg der Moment der BST-Eigenschaft verletzt wird. Prüfen, ob das Pfadsegment wir bisher gingen kann ein BST ist in O durchgeführt werden (1) Zeit, für eine O (PATH_LENGTH) Zeit Gesamtverarbeitungszeit, für jeden Knoten.

Am Ende wird jeder Knoten seinen entsprechenden S haben n besiedelt. Wir können den Baum jetzt gehen und den Knoten mit dem größten Wert von S Pick n .

Die Zeit dafür genommen ist die Summe der Tiefen des Knoten (im schlimmsten Fall), und das ist O (n log n) im Durchschnitt Fall (siehe Abschnitt 5.2.4 von http://www.toves.org/books/ data / CH05-Bäume / index.html ), aber O (n ^ 2) im ungünstigsten Fall.

Vielleicht ist ein cleverer Weg, um die Sätze zu aktualisieren wird eine Verringerung im schlimmsten Fall Zeit zu garantieren.

Der Pseudo-Code könnte etwa so aussehen:

static Tree void LargestBST(Tree t)
{
    LargestBST(t, new List<Pair>());
    // Walk the tree and return the largest subtree with max |S_n|.
}

static Tree LargestBST(Tree t, List<Pair> path)
{
    if (t == null) return;

    t.Set.Add(t.Value);

    int value = t.Value;
    int maxVal = value;
    int minVal = value;

    foreach (Pair p in path)
    {
        if (p.isRight)
        {
            if (minVal < p.node.Value)
            {
                break;
            }
        }

        if (!p.isRight)
        {
            if (maxVal > p.node.Value)
            {
                break;
            }
        }

        p.node.Set.Add(t.Value);

        if (p.node.Value <= minVal)
        {
            minVal = p.node.Value;
        }

        if (p.node.Value >= maxVal)
        {
            maxVal = p.node.Value;
        }
    }

    Pair pl = new Pair();
    pl.node = t;
    pl.isRight = false;

    path.Insert(0, pl);
    LargestBST(t.Left, path);

    path.RemoveAt(0);

    Pair pr = new Pair();
    pr.node = t;
    pr.isRight = true;

    path.Insert(0, pr);

    LargestBST(t.Right, path);

    path.RemoveAt(0);

}
Beantwortet am 02/07/2010 um 14:13
quelle vom benutzer

stimmen
0
GetLargestSortedBinarySubtree(thisNode, ref OverallBestTree)
    if thisNode == null
        Return null
    LeftLargest = GetLargestSortedBinarySubtree(thisNode.LeftNode, ref OverallBestTree)
    RightLargest = GetLargestSortedBinarySubtree(thisNode.RightNode, ref OverallBestTree)
    if LeftLargest.Max < thisNode.Value & RightLargest.Min > thisNode.Value
        currentBestTree = new BinaryTree(LeftLargest, thisNode.Value, RightLargest)
    else if LeftLargest.Max < thisNode.Value
        currentBestTree = new BinaryTree(LeftLargest, thisNode.Value, null)
    else if RightLargest.Min > thisNode.Value
        currentBestTree = new BinaryTree(null, thisNode.Value, RightLargest)
    else
        currentBestTree = new BinaryTree(null, thisNode.Value, null)
    if (currentBestTree.Size > OverallBestTree.Size)
        OverallBestTree = currentBestTree
    return currentBestTree

Wie BlueRaja wies darauf hin, ist dieser Algorithmus nicht korrekt.

Es sollte wirklich aufgerufen werden GetLargestSortedBinarySubtreeThatCanBeRecursivelyConstructedFromMaximalSortedSubtrees.

Beantwortet am 02/07/2010 um 19:46
quelle vom benutzer

stimmen
3

Der bisherige Algorithmus (siehe Versionen) war O(n^2)- wir haben es verallgemeinern kann O(n log n)durch zu bemerken , die Tatsachen , dass:

  1. Wenn b die Wurzel des größten BST ist und b.left.value < b.value, dann b.leftist auch in dem BST (gleiche gilt für b.right.value ≥ b.value)
  2. Wenn b die Wurzel des größten BST ist und A ist auch in der BST, so ist jeder Knoten zwischen a und b in dem BST.

Also , wenn c zwischen a und b, und c ist nicht in dem BST durch b verwurzelt, weder ein (wegen (2)) . Mit dieser Tatsache können wir leicht feststellen , ob ein Knoten in der BST von einem bestimmten Vorfahren verwurzelt ist. Wir werden dies tun , indem Sie einen Knoten in unsere Funktion zusammen mit einer Liste ihrer Vorfahren vorbei, und die damit verbundene min / MAXWERTE , dass der aktuelle Kind-Knoten müßte genügen , wenn in der Tat , dass Vorfahren die Wurzel des größten BST sind (wir ll nennen diese Liste ancestorList). Wir speichern die gesamte Sammlung von potenzial Wurzeln inoverallRootsList

Lassen Sie uns eine Struktur definieren genannt potentialRoot wie folgt:

Jede potentialRoot enthält die folgenden Werte:
* Knoten : Der Knoten , die wir für die Wurzel des BST erwägen
* minValue und maxValue : der Bereich ein weiterer Knoten zwischen fallen muss , durch den Knoten verwurzelten Teil des BST sein (unterschiedlich für jeden Knoten)
* Subknoten : Eine Liste der Rest der Knoten in der größten BST von Knoten wurzelt

Der Pseudo - Code sieht wie folgt aus (beachten Sie, dass alle genannten Listen , Listen potentialRoots sind) :

FindLargestBST(node, ancestorList):
    leftList, rightList = empty lists
    for each potentialRoot in ancestorList:
        if potentialRoot.minValue < node.Value ≤ potentialRoot.maxValue:
            add node to potentialRoot.subNodes (due to (1.))
            (note that the following copies contain references, not copies, of subNodes)
            add copy of potentialRoot to leftList, setting maxValue = node.Value
            add copy of potentialRoot to rightList, setting minValue = node.Value

    add the potentialRoot (node, -∞, +∞) to leftList, rightList, and overallRootsList
    FindLargestBST(node.left, leftList)
    FindLargestBST(node.right, rightList)

Am Ende overallRootsListwird eine Liste der sein npotentialRoots, die jeweils mit einer Liste der untergeordneten Knoten. Der mit der größten untergeordneten Knoten Liste ist Ihre BST.

Da es <treeHeight Werte in ancestorList, dann (vorausgesetzt , der Baum ausgeglichen ist), geht der Algorithmus läuft inO(n log n)

Beantwortet am 02/07/2010 um 20:21
quelle vom benutzer

stimmen
0
root(Tree L A R) = A

MaxBST(NULL) = (true, 0, NULL)
MaxBST(Tree L A R as T) = 
  let
    # Look at both children
    (L_is_BST, L_size, L_sub) = MaxBST(L)
    (R_is_BST, R_size, R_sub) = MaxBST(R)
  in
  # If they're both good, then this node might be good too
  if L_is_BST and R_is_BST and (L == NULL or root(L) < A) and (R == NULL or A < root(R))
  then (true, 1 + L_size + R_size, T)
  else
       # This node is no good, so give back the best our children had to offer
       (false, max(L_size, R_size), if L_size > R_size then L_sub else R_sub)

Sieht an jedem Baumknoten genau einmal, so läuft in O (N).

Edit: Crud, dies ist nicht der, dass es einige Teile eines Teilbaums auslassen kann. Als ich subtree lesen, nahm ich an „den gesamten Baum zu einem bestimmten Knoten verwurzelt“. Ich kann dies später zu beheben zurückkommen.

Beantwortet am 03/07/2010 um 01:15
quelle vom benutzer

stimmen
4

Diese Antwort enthielt zuvor ein O - Algorithmus basiert auf Link / gefällte Bäume (n log n). Hier ist eine einfache O (n) Lösung.

Der Kern ist ein Verfahren, das einen Knoten, die einzigartige maximale BSST verwurzelt an seinem linken Kind, das einzigartige maximale BSST verwurzelt an seinem rechten Kind, und Zeiger auf die am weitesten links und am weitesten rechts stehenden Elementen dieser BSSTs akzeptiert. Es zerstört seine Eingänge (vermeidbar mit persistenten Datenstrukturen) und konstruiert die eindeutige maximale BSST an dem gegebenen Knoten verwurzelte, zusammen mit seinem minimalen und maximalen Elementen. Alle BSST Knoten sind mit der Anzahl der Nachkommen kommentiert. Wie zuvor wird diese Prozedur wiederholt von einer Post-Order Traversal genannt. Um den Unterbaum zu erholen, erinnere mich an die Wurzel des größten BSST; es erfordert nur einen einfachen Traversal zu rekonstruieren.

Ich werde die linke BSST behandeln nur; der rechte ist symmetrisch. Wenn die Wurzel des linken BSST größer als die neue Wurzel ist, dann wird der gesamte Unterbaum wird entfernt und die neue Wurzel wird jetzt am weitesten links. Andernfalls wird der alte am weitesten links stehenden Knoten noch am weitesten links. Ausgehend von dem am weitesten rechts liegenden Knoten des linken BSST und nach oben bewegen, findet die ersten Knoten , die kleine oder gleich die Wurzel ist. Sein rechtes Kind muss entfernt werden; beachten Sie jetzt , dass aufgrund der BST Eigenschaft, müssen keine anderen Knoten gehen! Fahren Sie mit der Wurzel des linken BSST, die zählt die Aktualisierung der Löschung zu reflektieren.

Der Grund diese O (n) ist, ist, dass trotz der Schleife, wobei jede Kante in dem ursprünglichen Baum im wesentlichen nur einmal durchlaufen wird.


EDIT: gemeinsam durchlaufenen Pfade sind die maximale geradlinige Pfade in einem BST, mit Ausnahme der linken und der rechten Wirbelsäule Wirbelsäule. Zum Beispiel am Eingang

              H
             / \
            /   \
           /     \
          /       \
         /         \
        /           \
       /             \
      D               L
     / \             / \
    /   \           /   \
   /     \         /     \
  B       F       J       N
 / \     / \     / \     / \
A   C   E   G   I   K   M   O

hier sind die rekursive Aufrufe an dem jede Kante durchlaufen wird:

              H
             / \
            /   \
           /     \
          /       \
         /         \
        /           \
       /             \
      D               L
     / h             h \
    /   h           h   \
   /     h         h     \
  B       F       J       N
 / d     d h     h l     l \
A   C   E   G   I   K   M   O
Beantwortet am 03/07/2010 um 17:46
quelle vom benutzer

stimmen
1

GRÖSSTE binärer Suchbaum in einem Binärbaum:

Es gibt zwei Möglichkeiten, wie wir dieses Problem nähern können,

i) Größte BST nicht induziert (von einem Knoten, alle seine Kinder erfüllen müssen nicht die BST-Bedingung)

ii) Größte BST induziert (von einem Knoten, alle seine Kinder die BST Bedingung erfüllen)

Wir werden über die größte BST diskutieren hier (nicht induziert). Wir werden von unten nach oben Ansatz (Beitrag Order Traversal) folgen, diese zu lösen.

a) erreichen die Astknoten

b) Ein Baum-Knoten (aus dem Blatt) ein TreeNodeHelper Objekt zurück, das die folgenden Felder hat.

public static class TreeNodeHelper {
        TreeNode node;
        int nodes;
        Integer maxValue;
        Integer minValue;
        boolean isBST;


        public TreeNodeHelper() {}

        public TreeNodeHelper(TreeNode node, int nodes, Integer maxValue, Integer minValue, boolean isBST) {
            this.node = node;
            this.nodes = nodes;
            this.maxValue = maxValue;
            this.minValue = minValue;
            this.isBST = isBST;
        }      
    }

c) zunächst aus dem Blattknoten, Knoten = 1, isBST = true, minValue = maxValue = node.data. Und weiter: Zählen Sie die Knoten erhöht werden, wenn es die BST Bedingung erfüllt.

d) Mit Hilfe dieser, werden wir die BST Zustand mit aktuellen Knoten überprüfen. Und wir werden das gleiche bis Wurzel wiederholen.

e) Von jedem Knoten zwei Objekte zurückgegeben werden. ein für letztes Maximum BST und eine anderen für Strom BST befriedigendes Knoten. So von jedem Knoten (oberhalb Blatt) (2 + 2) = 4 (2 linken Teilbaum und 2 für die rechten Teilbaum) Objekte werden verglichen und zwei zurückgegeben.

f) Das letzte maximale Knotenobjekt von der Wurzel wird die größte BST sein

PROBLEM:

Es gibt ein Problem bei diesem Ansatz. Während dieses Ansatz folgen, wenn ein Teilbaum ist nicht den BST Zustand mit dem aktuellen Knoten erfüllen, können wir nicht einfach den Teilbaum ignorieren (selbst hat es eine geringere Anzahl von Knoten). Beispielsweise

 55
  \
   75
  /  \
 27  89
    /  \
   26  95
      /  \
     23  105
         /  \
        20  110

Von dem Blattknoten (20.110) werden die Objekte mit Knoten (105) geprüft werden, erfüllen sie die Bedingung. Aber wenn es Knoten erreicht (95) der Blattknoten (20) nicht erfüllt, den BST Zustand. Da diese Lösung für BST (nicht induziert) ist, sollten wir nicht-Knoten (105) und dem Knoten (110) ignorieren, die die Bedingung erfüllt. Also von dem Knoten (95) müssen wir ansetzen wieder BST Zustand zu testen und diese Knoten fangen (105, 110).

Der vollständige Code für diese Implementierung ist in diesem Link

https://github.com/dineshappavoo/Implementation/tree/master/LARGEST_BST_IN_BT_NOT_INDUCED_VER1.0

Beantwortet am 27/03/2014 um 00:48
quelle vom benutzer

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