98. 驗證二叉搜索樹
給定一個二叉樹,判斷其是否是一個有效的二叉搜索樹。
假設一個二叉搜索樹具有如下特徵:
- 節點的左子樹只包含小於當前節點的數。
- 節點的右子樹只包含大於當前節點的數。
- 所有左子樹和右子樹自身必須也是二叉搜索樹。
示例1:
輸入:
2
/ \
1 3
輸出: true
示例2:
輸入:
5
/ \
1 4
/ \
3 6
輸出: false
解釋: 輸入爲: [5,1,4,null,null,3,6]。
根節點的值爲 5 ,但是其右子節點值爲 4 。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/validate-binary-search-tree/
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
-
1. 遞歸法
思路:
- 遞歸終止條件爲當前節點爲空
- 判斷當前節點是否滿足二叉樹性質(左子樹都小於根節點 & 右子樹都大於根節點)
- 遞歸判斷左右子樹是否滿足條件
- 注意:要判斷右子樹中所有節點都要大於根節點纔可以
public boolean isValidBST(TreeNode root) {
return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
private 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);
}
複雜度分析:
時間複雜度:O(n), 需要遍歷所有節點進行判斷
空間複雜度:O(n), 遞歸深度可能達到n層
-
2. 迭代法
需要使用(中序遍歷)LeetCode 94. 二叉樹的中序遍歷 - 簡書
思路: 二叉搜索樹中序遍歷後的結果一定是從小到達排列的
public boolean isValidBST(TreeNode root) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
long res = Long.MIN_VALUE;
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
if (cur.val < res) return false;
else res = cur.val;
cur = cur.right;
}
return true;
}
複雜度分析:
時間複雜度:O(n), 最壞情況下我們需要遍歷每個元素添加到stack中
空間複雜度:O(n), 棧中需要存儲 n 個元素
-
3. 中序遍歷
思路:
- 創建 list,遞歸進行中序遍歷,將每個節點的值添加到 list中
- 遍歷 list, 判斷是否是從小到大進行排序的,如果是則一定是二叉搜索樹,否則一定不是
public boolean isValidBST(TreeNode root) {
List<Long> list = new ArrayList<>();
helper(root, list);
for (int i = 1; i < list.size(); i++) {
if (list.get(i) - list.get(i - 1) <= 0) return false;
}
return true;
}
private void helper(TreeNode root, List<Long> list) {
if (root == null) return;
helper(root.left, list);
list.add((long) root.val);
helper(root.right, list);
}
複雜度分析:
- 時間複雜度:O(n + n), 需要遍歷每個節點進行遞歸比較,最後還需要遍歷 list 查看順序
- 空間複雜度:O(n + n), 中序遍歷過程中使用了遞歸,並且還需要創建大小爲 n 的 list
-
源碼
-
我會每天更新新的算法,並儘可能嘗試不同解法,如果發現問題請指正
- Github