二叉树的训练

二叉搜索树变成二叉平衡树

二叉搜索树:
假设一个二叉搜索树具有如下特征:

节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。

二叉平衡搜索树:
具有搜索树的特点的基础上,同时左右节点的树的高度差不大于1.

在这里插入代码片
class Solution {
    
    ArrayList<Integer> list=new ArrayList<>();
    public void travel(TreeNode cur){
        if(cur==null){
            return;
        }
        travel(cur.left);
        list.add(cur.val);
        travel(cur.right);
    }
    public TreeNode getNode(List<Integer> num, int left, int right){
        if(left>right){
            return null;
        }
        if(left==right){
            return new TreeNode(num.get(left));
        }
        int mid=left+(right-left)/2;   //先得到的是中间的节点
        TreeNode root=new TreeNode(num.get(mid));
        root.left=getNode(num,left,mid-1);   //根节点的左节点是二分法之后的中间节点
        root.right=getNode(num,mid+1,right);
        return root;
    }
    public TreeNode balanceBST(TreeNode root) {
        travel(root);
        return getNode(list,0,list.size() - 1);
    }
}

思路
在这里的话,首先通过中序遍历,得到的是有序的链表,再通过二分法对root节点的左右节点进行创建新的节点。
直到左节点大于右节点的时候,终止。

二叉树的本质就是找到一个根节点,然后按照左右节点进行遍历,遍历的方式可以使用前中后遍历,
不过我一般喜欢使用前序遍历,前序遍历就是先打印出当前的节点的值,再进行左节点的打印,然后是右节点的打印,每一次左节点
打印后会回溯。

给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。

例如,

标题二叉搜索树中的搜索

在上述示例中,如果要找的值是 5,但因为没有节点值为 5,我们应该返回 NULL。

在这里插入图片描述本题当然可以前序遍历直接遍历完成,但是还是要利用一下搜素二叉树的性质:

    若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    它的左、右子树也分别为二叉搜索树

答案就呼之欲出了,就是当节点的值大于当前的值的时候寻找左节点,否则寻找右节点,然后终止条件是找到了节点或者说节点的值为空。

在这里插入代码片
class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        //注意给的是二叉搜索树,左边比节点小,右边大
        if(root==null||root.val==val){
            return root;//搜索结束
        }
        if(root.val>val){
            return searchBST(root.left,val);
        }else{
           return searchBST(root.right,val);
        }
    }
}

二叉搜索树的最小绝对差

这道题的关键就是变成中序遍历,然后更新最小的值

在这里插入图片描述中序遍历如图所示
首先执行的是 dfs(root.left);,回溯的终止条件是 if(root==null){ return; },然后进行中间值的打印,或者说更新当前的节点的值,此时进行回溯到当前点的值,进行比较更新:

    if(pre!=null){
        minLen=Math.min(minLen, Math.abs(pre.val-root.val));
    }

同时更新前一个点的值

在这里插入代码片
        pre=root;  //永远记录前一个的节点,中序遍历,此时应该是记录中间的节点

然后进行右节点的遍历。
总体的代码为:

在这里插入代码片
    int minLen=Integer.MAX_VALUE;
    TreeNode pre;
    public int getMinimumDifference(TreeNode root) {
        if(root==null){
            return 0;
        }
        dfs(root);
        return minLen;
    }
    public void dfs(TreeNode root){
        if(root==null){
            return;
        }
        dfs(root.left);

        if(pre!=null){
            minLen=Math.min(minLen, Math.abs(pre.val-root.val));
        }
        pre=root;  //永远记录前一个的节点,中序遍历,此时应该是记录中间的节点
        dfs(root.right);
    }


二叉树的最近公共祖先

我认为这道题是最好的二叉树题目,和那些递归,然后回溯的题目不同,这道题更能体现递归是如何进行回溯的
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        //显然是使用递归进行的求解,求解的方法是,求节点的左子树和右子树看看是否为null
        if(root==null ||root==p || root==q){
            return root;//终止条件
        }
        TreeNode left=lowestCommonAncestor(root.left,p,q); //递归的时候的左节点
        TreeNode right=lowestCommonAncestor(root.right,p,q);  //递归的时候的右子树
        //递归的时候的结果
        if(left==null &&right==null){
            return null;
        }
        if(left==null){
            return right;
        }
        if(right==null){
            return left;
        }
        return root;
    }
}

在这里插入图片描述这道题中终止条件显然是root==p || root==q,如果left 和 right都不为空,说明此时root就是最近公共节点,这也就是最后直接返回了root的原因。如果left为空,right不为空,就返回right,说明目标节点是通过right返回的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值