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
- 将此信息(计数器、开始、结束)节点存储在数组结构中,以便稍后查找具有最大值的节点,从而获得最长的二进制搜索子树
- 对于x的每个后代y,使得从n到y的路径是BST,y在Sn中
- 有趣的问题
我先前的尝试是愚蠢的错误
这里是另一个尝试(希望这次能纠正)
我假设这棵树是连通的
假设对于树的每个节点n,都有一组n,Sn的后代,其属性为
对于Sn的每个成员x,从n到x的唯一路径是一个二叉搜索树(它只是一个路径,但您仍然可以将其视为树)。
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