我试图找出一个逻辑来确定二进制树是否是BST。我想使用inorder方法,并且我不想使用额外的数组来存储所有传入的值,因为我们知道Inorder应该按排序顺序。我想检查传入的值,而不必将其存储在一个数组中。以下是我的尝试无效。
public bool CheckBST(BstNode root)
{
BstNode prev = new BstNode(Int32.MinValue);
if (root == null)
return true;
if (root.left != null)
{
return CheckBST(root.left);
}
if (prev != null && prev.data >= root.data) // means data is not sorted hence NOT BST
return false;
prev = root;
if(root.right!=null)
{
return CheckBST(root.right);
}
return true;
}
答案 0 :(得分:1)
给定二叉树,以下确定它是否是有效的二叉搜索树(BST)。
让我们看下面的例子:
如果您看到上面的二进制树是BST。
现在让我们看另一个例子:
根节点的值为5,但其右子的值为4,不满足上述条件。所以给定的树不是BST。
解决方案代码:
鉴于TreeNode被定义为
public class TreeNode
{
public int Val { get; set; }
public TreeNode Left { get; set; }
public TreeNode Right { get; set; }
public TreeNode(int x) { this.Val = x; }
}
检查验证的代码是
public bool IsValidBST(TreeNode root)
{
return IsValidBST(root, int.MinValue, int.MaxValue);
}
private bool IsValidBST(TreeNode root, int minValue, int maxValue)
{
if (root == null)
{
return true;
}
int nodeValue = root.Val;
if (nodeValue < minValue || nodeValue > maxValue)
{
return false;
}
return IsValidBST(root.Left, minValue, nodeValue - 1) && IsValidBST(root.Right, nodeValue + 1, maxValue);
}
现在可以使用根节点
调用IsValidBST
bool isValidBST = IsValidBST(rootNode);
答案 1 :(得分:0)
因此,通常在BST中,每个节点中有三件事。那是数据,左右两个指针。如果任何节点中有两个以上的指针可用,则它不是BST。最好在节点级别确定是否有更多的指针。你会通过搜索树来浪费时间和资源。
这是一个很好的方法https://www.geeksforgeeks.org/a-program-to-check-if-a-binary-tree-is-bst-or-not/
答案 2 :(得分:0)
您无法在prev
中每次初始化CheckBST
。您可以使prev
全局。此外,我已将prev
设为integer
类型。
int prev = Int32.MinValue; //made this global and integer type
public bool CheckBST(BstNode root) {
if (root == null)
return true;
bool isLeftBST = CheckBST(root.left);
if (isLeftBST == false) return false;
if (prev != Int32.MinValue && prev >= root.data) // means data is not sorted hence NOT BST
return false;
prev = root.data; //mark the prev before traversing the right subtree
return isLeftBST && CheckBST(root.right);
}
忽略语法问题,如果有的话。我尝试了更多伪代码。
当然,还有其他方法可以解决这个问题。就像到目前为止跟踪最小值和最大值一样(在@ user1672994答案中)。
答案 3 :(得分:0)
如果你可以让CheckBST
返回被检查BST的范围(min,max),那么下面的递归函数应该这样做:
// Defines the return value that represents BST check failure.
const pair<int, int> kCheckFailed(Int32.MaxValue, Int32.MinValue);
pair<int, int> CheckBST(const BstNode& curr)
{
pair<int, int> left_ret(curr.value, curr.value);
pair<int, int> right_ret(curr.value, curr.value);
// Makes sure the left subtree, if any, is a BST, and its max
// (`left_ret.second`) is no greater than `curr.value`
if (curr.left) {
left_ret = CheckBST(*curr.left);
if (left_ret == kCheckFailed || left_ret.second > curr.value)
return kCheckFailed;
}
// Makes sure the right subtree, if any, is a BST, and its min
// (`right_ret.first`) is not less than `curr.value`.
if (curr.right) {
right_ret = CheckBST(*curr.right);
if (right_ret == kCheckFailed || right_ret.first < curr.value)
return kCheckFailed;
}
// Returns range by combining min of left subtree and max of right subtree.
return make_pair(left_ret.first, right_ret.second);
}
请注意CheckBST
通过引用获取(子)树根,以确保节点(curr
)始终有效。但是,curr.left
或curr.right
可能仍然为NULL,在这种情况下,相应的最小值或最大值分别仅为curr.value
,初始化为ret_left
和{ {1}}。
答案 4 :(得分:0)
时间复杂度为 O(1)的递归。
删除注释行,以查看其调用方式。
对于首次通话isBST(root, null, null)
。
public bool isBST(Node root, Node l, Node r)
{
// Console.WriteLine($"Processing: isBST({root?.data}, {l?.data}, {r?.data})");
if (root == null) return true;
if (l != null && root.data <= l.data) return false;
if (r != null && root.data >= r.data) return false;
// Console.WriteLine($"isBST({root?.left?.data}, {l}, {root?.data}) && isBST({root?.right?.data}, {root?.data}, {r?.data})");
return isBST(root.left, l, root) && isBST(root.right, root, r);
}
答案 5 :(得分:-1)
您不需要上一步。
递归检查max(left)是否小于或等于root。
递归检查min(右)是否大于root。
检查左边是BST。
检查权利是否为BST。
当然,在需要的地方检查空值。