代码随想录训练营D20-二叉树篇 p6 | 654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树

(一) 654.最大二叉树

又是构造二叉树,昨天大家刚刚做完 中序后序确定二叉树,今天做这个 应该会容易一些, 先看视频,好好体会一下 为什么构造二叉树都是 前序遍历

题目/文章链接
视频讲解

1. 思路

递归
1)参数、返回值
参数:传入待排序的数组
返回值:返回当前这棵树的根结点。

2)终止条件
题目中给出,树结点数量至少为1,所以终止条件是 数组大小为1时,则当前结点就是未来的叶子结点,直接以该值创建一个节点并返回。

3)单层递归逻辑
以前序遍历创建树,先创建根节点,再为该根节点创建左右孩子。

  • 选出当前数组中的最大值,并记录其index下标
  • 使用该值创建一个树结点node。
  • 以该index位置,将数组划分左右两部分。
  • 递归左右两部分,并返回给node作为其左右子树。递归左右之前先要判断左右区间中至少有一个元素。!!

返回node。

1.1 直观思路

1.2 代码随想录思路

2. 代码

public static void main(String[] args) {
    Solution solution = new Q654ConstructMaximumBinaryTree().new Solution();
    TreeNode node = solution.constructMaximumBinaryTree(new int[]{3, 2, 1, 6, 0, 5});
    System.out.println();
}

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return buildHelper(nums, 0, nums.length);//这里注意 左闭右开,左右右侧到nums.length
    }

    private TreeNode buildHelper(int[] nums, int left, int right){
        //判空
        if(right <= left){
            return null;
        }
        //终止条件
        if(nums.length == 1){
            return new TreeNode(nums[0]);
        }

        //单层递归逻辑 前序遍历创建树
        //选出数组中的最大值,并记录下标index
        int index = 0;
        int maxValue = Integer.MIN_VALUE;
        for(int i = left; i < right; ++i){//注意这里i的范围 不是 0, nums.length
            if(nums[i] > maxValue){
                maxValue = nums[i];
                index = i;
            }
        }
        //System.out.println("index " + index + ", maxvalue " + maxValue);

        //创建节点
        TreeNode node = new TreeNode(maxValue);

        //切割数组
        int leftStart = left;
        int leftEnd = index;

        int rightStart = index + 1;
        int rightEnd = right;

        System.out.println("left [" + leftStart + "," + leftEnd + ")");
        System.out.println("left [" + rightStart + "," + rightEnd + ")");

        node.left = buildHelper(nums, leftStart, leftEnd);
        node.right = buildHelper(nums, rightStart, rightEnd);

        return node;
    }
}

3. 总结

1.判空时,何时以数组中没有元素为判断条件?何时以数组中只有一个元素为判断条件?

力扣题目中给出,树中至少有一个结点。则判空的判断条件是,数组中只有一个元素时。
力扣题目给出,树中可能有0个结点。则判空的判断条件是,数组中没有结点时。

2.所有涉及区间的地方都很容易出错。

(二) 617.合并二叉树

这次是一起操作两个二叉树了, 估计大家也没一起操作过两个二叉树,也不知道该如何一起操作,可以看视频先理解一下。 优先掌握递归。

题目/文章链接
视频链接

1. 思路

在这里插入图片描述
使用tree1的整体结构,tree1没有结点的位置直接使用tree2结点。

递归
1)参数:两个树的根结点;返回值:tree1的根结点。因为新树的根结点就是tree1的根结点。
2)递归终止条件。tree1结点为null,返回tree2(直接使用tree2的结点,此时tree2为null也没关系,返回合并后为null)。tree2的结点为null,返回tree1(此时tree1为null也没关系,返回合并后为null)。
3)单层递归逻辑。
对于构建二叉树,较直观的思路是前序遍历,根左右。
经过上面的递归终止条件,现在的tree1、tree2都不为null。

  • 根。tree1节点值 += tree2节点值
  • 递归处理左子树
  • 递归处理右子树

返回这个根。

2. 代码

public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
    //1.递归终止条件。题中说可能结点数为0,所以判空。
    if(root1 == null){
        return root2;
    }
    if(root2 == null){
        return root1;
    }

    //root1 root2 都不为null
    //2.单层递归逻辑
    root1.val += root2.val;
    root1.left = mergeTrees(root1.left, root2.left);
    root1.right = mergeTrees(root1.right, root2.right);

    return root1;
}

3. 学习到的东西

一个判空,也是递归终止条件。
这样包括了三种情形:都为null、其中只有一个为null

if(root1 == null){
    return root2;
}
if(root2 == null){
    return root1;
}

(三) 700.二叉搜索树中的搜索

递归和迭代 都可以掌握以下,因为本题比较简单, 了解一下 二叉搜索树的特性

题目/文章链接
视频链接

1. 思路

【1.递归】
1.返回值和参数
参数:根结点、目标值。返回值:该目标值所存在的树 的根结点。
2.终止条件
因为本题说明,至少有一个结点。所以终止条件:判断是否是叶子结点,若是叶子结点,判断其值与目标值是否相等,若相等,直接返回该节点;否则,返回null(表示该树中没有该值)
恭喜!上面是错的哈哈哈哈。

终止条件还得是,若为空节点,返回null。

3.单层递归逻辑-前序遍历
根。目标值与当前结点值相等,则直接 return
递归查找左右子树。
若最终都无,return null。

【2.迭代】
使用层序遍历,借助队列。

2. 代码

【1.递归】

public TreeNode searchBST(TreeNode root, int val) {
    //1.终止条件。是否是空结点
    if(root == null){
        return null;
    }

    if(root.val == val){
        return root;
    }else if(root.val > val){
        return searchBST(root.left, val);
    }else {
        return searchBST(root.right, val);
    }

}

【2.递归-优化】

将判空 和 目标值与当前结点值相等,在一起写了。

public TreeNode searchBST(TreeNode root, int val) {
    if (root == null || root.val == val) {
        return root;
    }
    if (val < root.val) {
        return searchBST(root.left, val);
    } else {
        return searchBST(root.right, val);
    }
}

【3.迭代】

//2.迭代
public TreeNode searchBST1(TreeNode root, int val) {
    //不判空 因为题目说了 至少有一个结点
    //1.创建队列
    Deque<TreeNode> queue = new ArrayDeque();
    queue.add(root);

    //2.开启外层循环,条件是队列不为空
    while(!queue.isEmpty()){
        //本题不需要区分每层,所以不需要内层循环
        TreeNode node = queue.poll();
        //开启判断,若该结点为查找的结点,则return
        if(node.val == val){
            return node;
        }
        if(node.left != null){
            queue.add(node.left);
        }
        if(node.right != null){
            queue.add(node.right);
        }
    }
    return null;
}

(四) 98.验证二叉搜索树

遇到 搜索树,一定想着中序遍历,这样才能利用上特性。
但本题是有陷阱的,可以自己先做一做,然后在看题解,看看自己是不是掉陷阱里了。这样理解的更深刻。

题目/文章链接
视频链接

1. 思路

建议使用中序遍历。因为搜索二叉树的中序遍历是严格递增的,所以设置一个变量存当前已遍历到的最大值max,在遍历时,若有值小于max,则false;

1.2 代码随想录思路

二叉搜索树可以为空,所以终止条件是,若为null,则返回true。

法1:使用long中最小值作为起始值,因为测试数据中会用到int的最小值。

法2:只用当前结点值 与 前一个节点值相比较的方法。
若当前值 比 前一个值大,则返回true,否则false

2. 代码

法1:使用Long.MIN 作为起始值

public boolean isValidBST(TreeNode root) {
    return isValid(root);
}

private long pre = Long.MIN_VALUE;
private boolean isValid(TreeNode node){
    //终止条件
    if(node == null){
        return true;
    }
    //中序遍历
    boolean left = isValidBST(node.left);
    if(node.val > pre){
        pre = node.val;
    }else {
        return false;
    }
    boolean right = isValidBST(node.right);
    return left && right;
}

法2(推荐):创建一个pre节点,用于与当前结点比较数值

public boolean isValidBST(TreeNode root) {
    return isValid(root);
}

//法2
private TreeNode preNode = null;
private boolean isValid(TreeNode node){
    if(node == null){
        return true;
    }

    boolean left = isValid(node.left);
    if(preNode != null && preNode.val >= node.val){
        return false;
    }
    preNode = node;
    boolean right = isValid(node.right);
    return left && right;
}

3.实现过程中的问题

写递归,脑子就错乱。问就是在梦游。

public boolean isValidBST(TreeNode root) {
	return isValid(root, Integer.MIN_VALUE);
}

private boolean isValid(TreeNode node, int value){
    if(node.left == null && node.right == null){
        if(node.val > value){
            value = node.val;
            return true;
        }else {
            return false;
        }
    }

    if(node.left != null){
        boolean left = isValid(node.left, value);
        if(!left){
            return false;
        }else{
            value = node.left.val;
        }
    }
    if(node.val <= value){
        return false;
    }else{
        value = node.val;
    }
    if(node.right != null){
        boolean right = isValid(node.right, value);
        if(!right){
            return false;
        }else{
            value = node.right.val;
        }
    }
    return true;
}

4. 总结

二叉搜索树的中序遍历严格递增的,要记得使用中序遍历体现其特性。

(五) 今日收获,记录一下自己的学习时长

题目类型:构造二叉树。都是使用先序遍历,先构造根节点,再为根节点添加左结点、右结点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值