leetcode-98-驗證二叉搜尋樹(validat binary search tree)-java
阿新 • • 發佈:2018-12-10
題目
package pid098; /*驗證二叉搜尋樹 給定一個二叉樹,判斷其是否是一個有效的二叉搜尋樹。 假設一個二叉搜尋樹具有如下特徵: 節點的左子樹只包含小於當前節點的數。 節點的右子樹只包含大於當前節點的數。 所有左子樹和右子樹自身必須也是二叉搜尋樹。 示例 1: 輸入: 2 / \ 1 3 輸出: true 示例 2: 輸入: 5 / \ 1 4 / \ 3 6 輸出: false 解釋: 輸入為: [5,1,4,null,null,3,6]。 根節點的值為 5 ,但是其右子節點值為 4 。 }*/ public class main { public static void main(String[] args) { Object[] x=new Object[]{3,1,20}; BinaryTree tree=new BinaryTree(x); tree.printTree(tree.root); test(tree.root); Object[] x2=new Object[]{10,5,15,null,null,6,20}; BinaryTree tree2=new BinaryTree(x2); tree2.printTree(tree2.root); test(tree2.root); } private static void test(TreeNode ito) { Solution solution = new Solution(); boolean rtn; long begin = System.currentTimeMillis(); rtn = solution.isValidBST(ito);//執行程式 long end = System.currentTimeMillis(); System.out.println("rtn=" ); System.out.print(rtn); System.out.println(); System.out.println("耗時:" + (end - begin) + "ms"); System.out.println("-------------------"); } }
注意:節點要大於左側所有子樹,而不是左側節點!!! 解法1(成功,1ms,很快) 遞迴演算法 如果以下四種情況,則返回false,否則為true 1 左節點的最右節點>自己 2 右節點的最左節點<自己 3 呼叫左節點為引數的這個方法返回false 4 呼叫右節點
之所以用左節點的最右,如果最右不是左側子樹的max 則在遞迴左子樹時會返回false
package pid098; import java.util.LinkedList; import java.util.List; /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public boolean isValidBST(TreeNode root) { if(root==null){ return true; } boolean result=true; if(root.left!=null){ if(getMaxVal(root.left)>=root.val){ result=false; } } if(root.right!=null){ if(getMinVal(root.right)<=root.val){ result=false; } } if(!isValidBST(root.left)){ result=false; } if(!isValidBST(root.right)){ result=false; } return result; } public int getMaxVal(TreeNode root){ while(root.right!=null){ root=root.right; } return root.val; } public int getMinVal(TreeNode root){ while(root.left!=null){ root=root.left; } return root.val; } }
方法2(別人的) 太厲害了! 用中序遍歷得到list,只要左邊大於右邊就ok
class Solution { public boolean isValidBST(TreeNode root) { if(root == null){ return true; } List<Integer> list = new ArrayList<Integer>(); inOrder(root,list); for(int i=0;i<list.size()-1;i++){ if(list.get(i) >= list.get(i+1)) return false; } return true; } private void inOrder(TreeNode root, List<Integer> list){ if(root == null){ return ; } inOrder(root.left,list); list.add(root.val); inOrder(root.right,list); } }
方法3(別人的) 同樣用遞迴的思想 也是利用了遞迴的思想,分別對每一個子樹進行判斷,但是它的亮點在於在判斷的時候並不需要對子樹進行搜尋“最相近的值”,而是利用了“最大值”、“最小值”的思想:
對於每個子樹,都有一個最大值和一個最小值,
對於左子樹,最大值就是它的根節點的值,最小值是根節點的最小值(左父親或者MIN_VALUE)
對於右子樹,最小值就是它的根節點的值,最大值是根節點的最大值(右父親或者MAX_VALUE)
例如:
5 / 1 6 / 3 7 5的滿足小於最大值,大於最小值,然後遞迴(1,MIN,5) && 遞迴(4,5,MAX) 。。。 3節點的最大值為6,最小值應該為5,此時不滿足,所以return false
即檢驗 left是否在 min 與val之間 right在 val與max之間
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);
}