題目
給定一棵二叉樹的頭節點head,已知其中所有節點的值都不一樣,找到含有節點最多的搜索二叉子樹,並返回這棵子樹的頭節點。例如,下圖中,右樹就是左樹的最大搜索子樹。
解題思路—後序遍歷:後序遍歷二叉樹,若當前結點的左右子樹都符合搜索二叉樹,就返回當前結點;若有左子樹(右子樹)不符合,則返回右子樹根節點(左子樹根節點)。需要設置全局變量來保存當前子樹的最大值、最小值以及節點數。
代碼不是特別好理解,所以給出了main,裏面已經建立了一棵與上圖中一樣的二叉樹,結合debug更易理解。
Java解題—後序遍歷
public static void main(String[] args) {
// 下面已經建立了一棵與示例圖中相同的二叉樹
TreeNode root = new TreeNode(6);
root.left = new TreeNode(1);
root.right = new TreeNode(12);
root.left.left = new TreeNode(0);
root.left.right = new TreeNode(3);
root.right.left = new TreeNode(10);
root.right.left.left = new TreeNode(4);
root.right.left.left.left = new TreeNode(2);
root.right.left.left.right = new TreeNode(5);
root.right.left.right = new TreeNode(14);
root.right.left.right.left = new TreeNode(11);
root.right.left.right.right = new TreeNode(15);
root.right.right = new TreeNode(13);
root.right.right.left = new TreeNode(20);
root.right.right.right = new TreeNode(16);
TreeNode sub = biggestSubBST(root);
}
public static TreeNode biggestSubBST(TreeNode head) {
// 記錄節點數,當前子樹的最大值,最小值
int[] record = new int[3];
return posOrder(head, record);
}
public static TreeNode posOrder(TreeNode head, int[] record) {
if (head == null) {
// 當遍歷到葉子節點時
record[0] = 0;
record[1] = Integer.MAX_VALUE;
record[2] = Integer.MIN_VALUE;
return null;
}
int value = head.val;// 頭節點的值
TreeNode left = head.left;// 左子樹的頭節點
TreeNode right = head.right;// 右子樹的頭節點
TreeNode lBST = posOrder(left, record);
int lSize = record[0];
int lMin = record[1];
int lMax = record[2];
TreeNode rBST = posOrder(right, record);
int rSize = record[0];
int rMin = record[1];
int rMax = record[2];
// 保存當前子樹中的最大值與最小值,不是隻保存左子樹的最大值與右子樹的最小值
// 因爲在遞歸的過程中,不知道當前是左子樹還是右子樹
record[1] = Math.min(lMin, value);
record[2] = Math.max(rMax, value);
// left == lBST && right == rBST 這個判斷條件特別重要
// 只有當左右兩個子樹的根節點是當前節點的左右子節點,當前節點才能作爲根節點加入
if (left == lBST && right == rBST && lMax < value && value < rMin) {
record[0] = lSize + rSize + 1;
return head;
}
record[0] = Math.max(lSize, rSize);
// 若左右子樹不能合併,返回當前最長的那個子樹的根節點
return lSize > rSize ? lBST : rBST;
}