題目詳情
給你一個(gè)二叉樹的根節(jié)點(diǎn) root ,判斷其是否是一個(gè)有效的二叉搜索樹。
有效 二叉搜索樹定義如下:
- 節(jié)點(diǎn)的左子樹只包含 小于 當(dāng)前節(jié)點(diǎn)的數(shù)。
- 節(jié)點(diǎn)的右子樹只包含 大于 當(dāng)前節(jié)點(diǎn)的數(shù)。
- 所有左子樹和右子樹自身必須也是二叉搜索樹。
提示:
- 樹中節(jié)點(diǎn)數(shù)目范圍在[1, 104] 內(nèi)
- -2^31 <= Node.val <= 2^31 - 1
示例 1:
輸入:root = [2,1,3]
輸出:true
2
/ \
1 3
示例 2:
輸入:root = [5,1,4,null,null,3,6]
輸出:false
解釋:根節(jié)點(diǎn)的值是 5 ,但是右子節(jié)點(diǎn)的值是 4 。
5
/ \
1 4
/ \
3 6
Java代碼(遞歸)
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;
//每個(gè)節(jié)點(diǎn)如果超過這個(gè)范圍,直接返回false
if (root.val >= maxVal || root.val <= minVal)
return false;
//這里再分別以左右兩個(gè)子節(jié)點(diǎn)分別判斷,
//左子樹范圍的最小值是minVal,最大值是當(dāng)前節(jié)點(diǎn)的值,也就是root的值,因?yàn)樽笞訕涞闹狄犬?dāng)前節(jié)點(diǎn)小
//右子數(shù)范圍的最大值是maxVal,最小值是當(dāng)前節(jié)點(diǎn)的值,也就是root的值,因?yàn)橛易訕涞闹狄犬?dāng)前節(jié)點(diǎn)大
return isValidBST(root.left, minVal, root.val) && isValidBST(root.right, root.val, maxVal);
}
總結(jié)
遞歸的結(jié)束條件是遇到了葉子節(jié)點(diǎn),如果遇到了葉子節(jié)點(diǎn)就返回true。如果當(dāng)前節(jié)點(diǎn)的值大于最大值或者小于最小值那么返回false。然后用遞歸判斷左子樹和右子樹是否是二叉搜索樹,這時(shí)需要將當(dāng)前節(jié)點(diǎn)的值來判斷左子樹是否符合條件,因?yàn)樽蠊?jié)點(diǎn)的值永遠(yuǎn)小于父節(jié)點(diǎn),所以需要將當(dāng)前節(jié)點(diǎn)值作為左子樹的最大值,這樣就能將左子樹的所有值限制為小于父節(jié)點(diǎn),右子樹同理。
Java代碼(中序遍歷)
//前一個(gè)結(jié)點(diǎn),全局的
TreeNode prev;
public boolean isValidBST(TreeNode root) {
if (root == null)
return true;
//訪問左子樹
if (!isValidBST(root.left))
return false;
//訪問當(dāng)前節(jié)點(diǎn):如果當(dāng)前節(jié)點(diǎn)小于等于中序遍歷的前一個(gè)節(jié)點(diǎn)直接返回false。
if (prev != null && prev.val >= root.val)
return false;
prev = root;
//訪問右子樹
if (!isValidBST(root.right))
return false;
return true;
}
總結(jié)
根據(jù)二叉搜索樹的性質(zhì),中序遍歷二叉搜索樹,遍歷得到的結(jié)果一定是有序的,所以在遍歷過程中,判斷當(dāng)前節(jié)點(diǎn)是否大于前一個(gè)節(jié)點(diǎn),如果不是有序,那么返回false。