【LeetCode】Validate Binary Search Tree 驗證二叉查詢樹
阿新 • • 發佈:2019-02-08
驗證二叉查詢樹
給定一個二叉樹,判斷它是否是合法的二叉查詢樹(BST)
一棵BST定義為:
節點的左子樹中的值要嚴格小於該節點的值。
節點的右子樹中的值要嚴格大於該節點的值。
左右子樹也必須是二叉查詢樹。
一個節點的樹也是二叉查詢樹。
樣例
一個例子:
2
/ \
1 4
/ \
3 5
上述這棵二叉樹序列化為 {2,1,4,#,#,3,5}.
標籤
分治法 二叉樹 遞迴 二叉查詢樹
【分析】
SOLUTION 1:
使用Iterator 中序遍歷的方法,判斷整個數列是否保持增序即可。
演算法思想:
- 採用棧的話,先尋找最左邊的節點,把經過的節點都存入棧中,第一個被彈出來的為最左節點,那麼訪問其右子樹,對右子樹也像前面一樣遍歷,整個流程跟遞迴一樣。
public boolean isValidBST1(TreeNode root) {
// Just use the inOrder traversal to solve the problem.
if (root == null) {
return true;
}
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode cur = root;
TreeNode pre = null;
while (true) {
// Push all the left node into the stack.
while (cur != null) {
s.push(cur);
cur = cur.left;
}
if (s.isEmpty()) {
break;
}
// No left node, just deal with the current node.
cur = s.pop();
if (pre != null && pre.val >= cur.val) {
return false;
}
pre = cur;
// Go to the right node.
cur = cur.right;
}
return true;
}
我們可以設定上下bound,遞迴左右子樹時,為它們設定最大值,最小值,並且不可以超過。
注意:下一層遞迴時,需要把本層的up 或是down繼續傳遞下去。相當巧妙的演算法。
/*
SOLUTION 2: Use the recursive version.
REF: http://blog.csdn.net/fightforyourdream/article/details/14444883
*/
public boolean isValidBST2(TreeNode root) {
// Just use the inOrder traversal to solve the problem.
if (root == null) {
return true;
}
return dfs(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
public boolean dfs(TreeNode root, long low, long up) {
if (root == null) {
return true;
}
if (root.val >= up || root.val <= low) {
return false;
}
return dfs(root.left, low, root.val)
&& dfs(root.right, root.val, up);
}
Solution 3:
使用一個全域性變數,用遞迴的中序遍歷來做,也很簡單(但全域性變數主頁君不推薦!)
/*
SOLUTION 3: Use the recursive version3.
*/
TreeNode pre = null;
public boolean isValidBST(TreeNode root) {
// Just use the inOrder traversal to solve the problem.
return dfs4(root);
}
public boolean dfs4(TreeNode root) {
if (root == null) {
return true;
}
// Judge the left tree.
if (!dfs4(root.left)) {
return false;
}
// judge the sequence.
if (pre != null && root.val <= pre.val) {
return false;
}
pre = root;
// Judge the right tree.
if (!dfs4(root.right)) {
return false;
}
return true;
}
(4)Java
SOLUTION 4:
同樣是遞迴,但是把左右子樹的min, max值返回,與當前的root值相比較。比較直觀。
/**
* Definition of TreeNode:
* public class TreeNode {
* public int val;
* public TreeNode left, right;
* public TreeNode(int val) {
* this.val = val;
* this.left = this.right = null;
* }
* }
*/
class ResultType{
boolean is_bst;
int maxValue, minValue;
public ResultType(boolean is_bst, int maxValue, int minValue) {
this.is_bst = is_bst;
this.maxValue = maxValue;
this.minValue = minValue;
}
}
public class Solution {
/*
* @param root: The root of binary tree.
* @return: True if the binary tree is BST, or false
*/
private ResultType ValidateBstHelper(TreeNode root){
if(root == null){
return new ResultType(true, Integer.MIN_VALUE, Integer.MAX_VALUE);
//當前節點無效,傳入false。
//Trick: 而傳入整型的最大/小值是為了避免影響最後Math.max/min()的判斷
}
ResultType left = ValidateBstHelper(root.left);
ResultType right = ValidateBstHelper(root.right);
// if(root.left == null || root.right == null){
if(!left.is_bst || !right.is_bst){
return new ResultType(false, 0, 0);
//以當前節點為根的子bst是無效的。故傳入false,但他本身節點非空,說明確實存在該節點,故後面傳入0(因為無用)
// if is_bst is false then minValue and maxValue are useless
}
if(root.left != null && left.maxValue >= root.val ||
root.right != null && right.minValue <= root.val){//正常的bst應滿足max(左子樹)<root<min(右子樹)。此處列舉不合法的bst。
return new ResultType(false, 0, 0);
}
return new ResultType(true, Math.max(root.val, right.maxValue), Math.min(root.val, left.minValue) );//以便回撥
}
public boolean isValidBST(TreeNode root) {
ResultType r = ValidateBstHelper(root);
return r.is_bst;
}
}
(2)C++
// version 1: traverse
class Solution {
private:
TreeNode *lastNode = NULL;
public:
/**
* @param root: The root of binary tree.
* @return: True if the binary tree is BST, or false
*/
bool isValidBST(TreeNode *root) {
if (root == NULL) {
return true;
}
if (!isValidBST(root->left)) {
return false;
}
if (lastNode != NULL && lastNode->val >= root->val) {
return false;
}
lastNode = root;
return isValidBST(root->right);
}
};
// traverse 2: divide & conquer
class ResultType {
public:
bool isBST;
TreeNode *maxNode, *minNode;
ResultType() {
this->isBST = true;
this->maxNode = NULL;
this->minNode = NULL;
}
};
class Solution {
public:
/**
* @param root: The root of binary tree.
* @return: True if the binary tree is BST, or false
*/
bool isValidBST(TreeNode *root) {
ResultType result = helper(root);
return result.isBST;
}
ResultType helper(TreeNode *root) {
ResultType result;
if (root == NULL) {
return result;
}
ResultType left = helper(root->left);
ResultType right = helper(root->right);
if (!left.isBST || !right.isBST) {
result.isBST = false;
return result;
}
if (left.maxNode != NULL && left.maxNode->val >= root->val) {
result.isBST = false;
return result;
}
if (right.minNode != NULL && right.minNode->val <= root->val) {
result.isBST = false;
return result;
}
result.isBST = true;
result.minNode = left.minNode == NULL ? root : left.minNode;
result.maxNode = right.maxNode == NULL ? root : right.maxNode;
return result;
}
};