定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:
创建一个根节点,其值为 nums 中的最大值。
递归地在最大值 左边 的 子数组前缀上 构建左子树。
递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums 构建的 最大二叉树 。
构造二叉树:用的是前序遍历,因为我得先构造根节点,然后构造左子树,再构造右子树
我们用递归函数 construct(nums,left,right) 表示对数组 nums 中从 nums[left] 到 nums[right] 的元素构建一棵树。我们首先找到这一区间中的最大值,记为 nums 中从 nums[best],这样就确定了根节点的值。随后我们就可以进行递归:
左子树为 construct(nums,left,best−1);
右子树为 construct(nums,best+1,right)。
当递归到一个无效的区间(left>right)时,便可以返回一棵空的树。
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return build(nums,0,nums.length-1);
}
public TreeNode build(int nums[],int left , int right){
if(left > right) return null;
int val = left;
for(int i = left ; i <= right; i++){
if(nums[i] > nums[val] ){
val = i;
}
}
TreeNode node = new TreeNode(nums[val]);
node.left = build(nums, left, val-1);
node.right = build(nums, val+1, right);
return node;
}
}
本题采用前序遍历,因为从根节点合并,顺着往下遍历左右,这样符合逻辑。
三部曲
1:判断返回值和类型,首先我要两个树同时遍历,那么返回值一定是两个树的节点,返回类型是一个新树,所以是TreeNode
2 判断终止条件:如果树1的左子树为null,则返回树2,反之亦然.
3 单层递归逻辑,前序遍历:首先节点相加,然后递归左节点,再递归右节点
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if(root1 == null) return root2;
if(root2 == null) return root1;
root1.val += root2.val;
root1.left = mergeTrees(root1.left,root2.left);
root1.right = mergeTrees(root1.right,root2.right);
return root1;
}
}
二叉搜索树是一个有序树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉搜索树
这就决定了,二叉搜索树,递归遍历和迭代遍历和普通二叉树都不一样。
- 确定递归函数的参数和返回值:递归函数的参数传入的就是根节点和要搜索的数值,返回的就是以这个搜索数值所在的节点。
- 确定终止条件如果root为空,或者找到这个数值了,就返回root节点。
- 确定单层递归的逻辑 看看二叉搜索树的单层递归逻辑有何不同。因为二叉搜索树的节点是有序的,所以可以有方向的去搜索。如果root.val > val,搜索左子树,如果root.val < val,就搜索右子树,最后如果都没有搜索到,就返回NULL。
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
if(root == null || root.val == val ) return root;
TreeNode result = new TreeNode();
if(root.val > val){
result = searchBST(root.left, val);
}
if(root.val < val){
result = searchBST(root.right,val);
}
return result;
}
}
有效 二叉搜索树定义如下:
- 节点的左子树只包含 小于 当前节点的数。
- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
中序遍历为升序
代码误区:单纯的比较左节点小于中间节点,右节点大于中间节点
我们要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点。
代码误区:样例中最小节点 可能是int的最小值,如果这样使用最小的int来比较也是不行的。
此时可以初始化比较元素为longlong的最小值。
class Solution {
// 递归
TreeNode max;
public boolean isValidBST(TreeNode root) {
if (root == null) {
return true;
}
// 左
boolean left = isValidBST(root.left);
if (!left) {
return false;
}
// 中
if (max != null && root.val <= max.val) {
return false;
}
max = root;
// 右
boolean right = isValidBST(root.right);
return right;
}
}