给定一个BST树,我们必须根据输入(N)将树分成两个子树,其中subtree1由所有节点组成,小于或等于N,子树2由所有节点组成。大于N。
50
/ \
40 60
/ \ /
30 45 55
\
58
输出:
50
/
40
/ \
30 45
60
/
55
\
58
我已经提出了以下算法,但它无法正常工作:
static Node splitTree(Node root, Node root2, int k){
if(root == null)
return null;
while(root != null){
if(root.data > k)
root = root.left;
else if(root.data < k)
root = root.right;
else
{
root2=root.right;
root.right=null;
break;
}
}
return root2;
}
答案 0 :(得分:6)
你不需要root2
参数,因为那是函数的结果,无论如何都会覆盖传递的任何值。
分割算法通常不仅需要剪切边缘(制作两棵树),而且还要在截止树的更深层次重复此操作,因为那里可能存在应该附加的子树发生了截止。
例如,如果您的树看起来像这样:
16
+---------------+---------------+
8 24
+-------+-------+ +-------+-------+
4 12 20 28
+---+---+ +---+---+ +---+---+ +---+---+
2 6 10 14 18 22 26 30
+-+-+ +-+-+ +-+-+ +-+-+ +-+-+ +-+-+ +-+-+ +-+-+
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31
你希望用k = 11
切割,然后两棵树看起来像这样:
8
+-------+-------+
4 10
+---+---+ +---+---+
2 6 9 11
+-+-+ +-+-+
1 3 5 7
16
+---------------+---------------+
12 24
+-------+ +-------+-------+
14 20 28
+---+---+ +---+---+ +---+---+
13 15 18 22 26 30
+-+-+ +-+-+ +-+-+ +-+-+
17 19 21 23 25 27 29 31
注意如何切割和更换多个边缘:16-8用16-12替换,8-12用8-10替换。这可以重复几次,并且对应于在树中找到(放置)目标值的数字侧开关(在左侧和右侧之间)。
建议代码:
static void setChild(Node node, boolean toLeft, Node child){
// Assign child node to the indicated direction: left or right
if (toLeft) {
node.left = child;
} else {
node.right = child;
}
}
static Node splitTree(Node root, int k){
Node root2 = null;
Node parent1 = null;
Node parent2 = null;
// Determine at which side of the root we will travel
boolean toLeft = root != null && k < root.data;
while (root != null) {
while (root != null && (k < root.data) == toLeft) {
parent1 = root;
root = toLeft ? root.left : root.right;
}
setChild(parent1, toLeft, null); // Cut out the edge. root is now detached
toLeft = !toLeft; // toggle direction
if (root2 == null) {
root2 = root; // This is the root of the other tree.
} else if (parent2 != null) {
setChild(parent2, toLeft, root); // re-attach the detached subtree
}
parent2 = parent1;
parent1 = null;
}
return root2;
}
上查看它
答案 1 :(得分:1)
public TreeNode[] splitBST(TreeNode root, int V) {
if (root == null) {
return new TreeNode[] { null, null };
}
if (root.val > V) {
TreeNode[] l = splitBST(root.left, V);
root.left = l[1];
return new TreeNode[] { l[0], root };
} else {
TreeNode[] r = splitBST(root.right, V);
root.right = r[0];
return new TreeNode[] { root, r[1] };
}
}
答案 2 :(得分:0)
我们可以通过递归来解决问题。
我们创建一个函数,将一对节点返回到所需的拆分树
class pair{
node small, big;
}
我们的功能如下pair splitBST(node root, int k)
Algo:
1 //check if root is null, both trees are empty
if (root == null)
return pair(null, null)
2 //check if root.data > k. In this case we know that nodes smaller than k lies in left subtree since it's given that we have BST
//Also, root will become part of pair.big
if (root.data > k)
pair leftAns = splitBST(root.left, k)
//this contains two trees-small and big where big needs to be updated as there might be nodes in left subtree that are greater than k
root.left = leftAns.big
leftAns.big = root
return leftAns
3 //for all other cases, we have to scan right subtree. This time root will become part of pair.small
pair rightAns = splitBST(root.right, k)
root.right = rightAns.small
rightAns.small = root
return rightAns
注意:在考虑递归解决方案时,总是假设我的函数在所有情况下都返回正确的答案;不要以为它是如何做到的。