二叉搜索樹定義
Assume a BST is defined as follows:
The left subtree of a node contains only nodes with keys less >than the node’s key.
The right subtree of a node contains only nodes with keys >greater than the node’s key.
Both the left and right subtrees must also be binary search trees.
先來踩坑
if(root == null)
return true;
if(root.left == null && root.right == null)
return true;
if(root.left == null)
return root.val < root.right.val && isValidBST(root.right);
if(root.right == null)
return root.val > root.left.val && isValidBST(root.left);
return root.left.val < root.val && root.val < root.right.val &&
isValidBST(root.right) && isValidBST(root.left);
上述解法是第一反應,說明了大多數第一反應是不可靠的,繼續修煉^-^
上述算法錯在只考慮了當前結點及其左右子節點的數值大小關係,跟二叉搜索樹的定義相差了十萬八千里。
下面記錄正確的解法
中序遍歷法:
利用遞歸進行遍歷,list儲存遍歷結果,判斷是否是二叉搜索樹是基於中序遍歷結果是否爲嚴格單調遞增序列。
public boolean isValidBST(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
isvalidbst(root,list);
for(int i = 0;i < list.size()-1;i++){
if(list.get(i) >= list.get(i + 1))
return false;
}
return true;
}
public void isvalidbst(TreeNode root,List<Integer> list){
if(root == null)
return;
isvalidbst(root.left,list);
list.add(root.val);
isvalidbst(root.right,list);
}
利用棧進行中序遍歷,中間需要用到一個pre的引用,來指向當前節點的父親節點,思想是中序遍歷出的序列一定是單調遞增的序列。
public boolean isValidBST(TreeNode root) {
if (root == null) return true;
Stack<TreeNode> stack = new Stack<>();
TreeNode pre = null;
while (root != null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
if(pre != null && root.val <= pre.val) return false;
pre = root;
root = root.right;
}
return true;
}
還有一種方法,思路是給需要遍歷的子樹指定最大最小值,對於左子樹,最大值不能超過其父節點,對於右子樹,最小值要大於父節點。
public boolean isValidBST(TreeNode root) {
return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
public boolean isValidBST(TreeNode root, long minVal, long maxVal) {
if (root == null) return true;
if (root.val >= maxVal || root.val <= minVal) return false;
return isValidBST(root.left, minVal, root.val) && isValidBST(root.right, root.val, maxVal);
}