Algorithm 对于给定的二叉树,找到最大二叉搜索子树

Algorithm 对于给定的二叉树,找到最大二叉搜索子树,algorithm,binary-tree,binary-search-tree,Algorithm,Binary Tree,Binary Search Tree,对于给定的二叉树,找到最大的子树,也就是二叉搜索树 例如: 输入: 10 / \ 50 150 / \ / \ 25 75 200 20 / \ / \ / \ / \ 15 35 65 30 120 135 155 250

对于给定的二叉树,找到最大的子树,也就是二叉搜索树

例如:

输入:

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

                   50
                  /   \
                 25   75
                / \   /
               15 35  65

如果按顺序遍历,二叉搜索树将为您提供排序结果。所以,对整个二叉树进行顺序遍历。排序最长的序列是最大的二进制搜索子树

  • 按顺序遍历元素(访问左、访问根、访问右)
  • 执行此操作时,获取节点数据,比较上一个节点数据是否小于下一个数据。如果是,则将计数器增加1。存储开始节点
  • 当比较失败时,存储结束节点并将计数器重置为0
  • 将此信息(计数器、开始、结束)节点存储在数组结构中,以便稍后查找具有最大值的节点,从而获得最长的二进制搜索子树
    • 有趣的问题

      我先前的尝试是愚蠢的错误

      这里是另一个尝试(希望这次能纠正)

      我假设这棵树是连通的

      假设对于树的每个节点n,都有一组n,Sn的后代,其属性为

        对于Sn的每个成员x,从n到x的唯一路径是一个二叉搜索树(它只是一个路径,但您仍然可以将其视为树)。

      • 对于x的每个后代y,使得从n到y的路径是BST,y在Sn中

      节点Sn的集合为您提供了以n为根的最大BST

      我们可以通过在树上进行深度优先搜索,传入路径信息(从根到当前节点的路径),并通过沿路径回溯更新路径中的节点集,为每个节点构造Sn

      当我们访问一个节点时,我们沿着路径向上走,并检查到目前为止所走的那一段路径是否满足BST属性。如果是这样,我们将当前节点添加到我们刚才走到的路径的相应节点集中。一旦BST属性被违反,我们就停止在路径上行走。检查到目前为止我们所走的路径段是否是BST可以在O(1)时间内完成,对于O(路径长度)时间,每个节点的总处理时间

      最后,每个节点将填充其相应的Sn。我们现在可以遍历树并选择Sn值最大的节点

      所用时间为节点深度之和(最坏情况下),在平均情况下为O(nlogn)(见的第5.2.4节),但在最坏情况下为O(n^2)

      也许更新集合的更聪明的方法可以保证在最坏的情况下减少时间

      伪代码可能类似于:

      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);
      
      }
      
      静态树无效最大BST(树t)
      {
      最大BST(t,新列表());
      //走到树上,返回最大的子树max | S|n |。
      }
      静态树最大BST(树t,列表路径)
      {
      如果(t==null)返回;
      t、 设置。添加(t值);
      int值=t值;
      int maxVal=值;
      int minVal=值;
      foreach(路径中的p对)
      {
      如果(p.isRight)
      {
      if(最小值p.node.Value)
      {
      打破
      }
      }
      p、 node.Set.Add(t.Value);
      if(p.node.Value=maxVal)
      {
      maxVal=p.node.Value;
      }
      }
      Pair pl=新的Pair();
      pl.node=t;
      pl.isRight=false;
      插入(0,pl);
      最大BST(t.左,路径);
      移除路径(0);
      Pair pr=新的Pair();
      pr.node=t;
      pr.isRight=true;
      插入路径(0,pr);
      最大BST(t.右侧,路径);
      移除路径(0);
      }
      
      GetLargestSortedBinarySubtree(此节点,参考总体最佳树)
      如果thisNode==null
      返回空值
      LeftMaximum=GetLargestSortedBinarySubtree(thisNode.LeftNode,参考总体最佳树)
      RightMaximum=GetLargestSortedBinarySubtree(thisNode.RightNode,参考总体最佳树)
      如果leftmaxist.MaxthisNode.Value
      currentBestTree=新的二进制树(LeftMaximum,thisNode.Value,RightMaximum)
      如果leftmaxist.MaxthisNode.Value,则为else
      currentBestTree=new BinaryTree(null,thisNode.Value,rightMaximum)
      其他的
      currentBestTree=new BinaryTree(null,thisNode.Value,null)
      如果(currentBestTree.Size>OverallBestTree.Size)
      总体最佳树=当前最佳树
      返回当前最佳树
      
      正如BlueRaja指出的,这种算法是不正确的

      它真的应该被称为
      getlargestsortedbinarysubtreethat,它可以从maximalsortedsubtrees构建而成
      以前的算法(见修订版)是
      O(n^2)
      -我们可以通过注意以下事实将其概括为
      O(n log n)

    • 如果b是最大BST的根且
      b.left.value
      ,则
      b.left
      也在BST中(与
      b.right.value相同≥ b、 值
    • 如果b是最大BST的根,a也在BST中,那么a和b之间的每个节点都在BST中
    • 因此,如果c在a和b之间,并且c不在以b为根的BST中,那么a也不是(由于(2.))。利用这一事实,我们可以很容易地确定一个节点是否位于BST中,其根由任何给定的祖先。我们将通过将一个节点及其祖先列表以及当前子节点必须满足的相关min/maxvalue(如果该祖先确实是最大BST的根)一起传递到我们的函数中来实现这一点(我们将此列表称为
      ancestorList
      )。我们将潜在根的整个集合存储在
      overallRootsList

      让我们定义一个名为potentialRoot的结构,如下所示:

      每个潜在根包含以下值:
      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
      
      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)
      
      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)
      
                    H
                   / \
                  /   \
                 /     \
                /       \
               /         \
              /           \
             /             \
            D               L
           / \             / \
          /   \           /   \
         /     \         /     \
        B       F       J       N
       / \     / \     / \     / \
      A   C   E   G   I   K   M   O
      
                    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
      
      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;
              }      
          }
      
       55
        \
         75
        /  \
       27  89
          /  \
         26  95
            /  \
           23  105
               /  \
              20  110